IntelliJ project has two modules: Spring Data Rest app and client. Both apps are Spring bootable apps. I made a lot of tests at client and now before every test iteration I have to run the rest service manually.
Test class looks like that:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {BusinessRepositoryImpl.class})
public class BusinessLogoRepositoryTest {
..
}
Here is the service:
#EnableAutoConfiguration
#ImportResource({
"classpath:spring/persistenceContext.xml"
})
#Import(DataServiceConfiguration.class)
public class Application {
public static void main(String[] args) throws Exception {
SpringApplication.run(Application.class, args);
}
}
So the question is if it's possible somehow to add the context of service to test class and run the service before test's start.
You can create a TestSuite with 2 methods annotated with #BeforeClass and #AfterClass to start the service before the tests and stop it after the tests are done.
Draft code to visualize :) what I mean is below.
#RunWith(SpringJUnit4ClassRunner.class)
#SuiteClasses({UnitTest1.class, UnitTest2.class, ... })
#EnableAutoConfiguration
#ImportResource({
"classpath:spring/persistenceContext.xml"
})
#Import(DataServiceConfiguration.class)
public class TestSuite {
#BeforeClass
public void start() throws Exception {
SpringApplication.run(Application.class, args);
}
#AfterClass
public void start() throws Exception {
SpringApplication.shutdown();
}
}
Related
I have a customized spring-boot-starter which will call some REST APIs when it gets a spring application event of ApplicationReadyEvent, so the configuration class is something like:
#Configuration
public class MySpringBootStarter {
#EventListener(ApplicationReadyEvent.class)
public void init() {
// Call REST APIs here
}
}
Then, I want to test the starter using MockServer which requires creating some expectations before the test runs. The test class may look like as follows:
#ExtendWith(MockServerExtension.class)
#SpringBootTest
#ContextConfiguration
#MockServerSettings(ports = {28787, 28888})
public class MySpringBootStarterTest {
private MockServerClient client;
#BeforeEach
public void beforeEachLifecycleMethod(MockServerClient client) {
this.client = client;
//creating expectations here
}
#Test
void shouldBeTrue() {
assertThat(true).isTrue();
}
#SpringBootApplication
static class MyTest {
public void main(String[] args) {
SpringApplication.run(Test.class, args);
}
}
}
But in fact, the expectations are always created after the ApplicationReadyEvent, viz., the init method of MySpringBootStarter class is called before the the beforeEachLifecycleMethod method in MySpringBootStarterTest class.
How can I make the test work, please?
You can use static block initializer to run required code before SpringContext boots up.
I have a basic spring data application and I have written a unit test. What appears to happen is that when I run the Spring test my application run method gets called as well. I would like to know why this is and how to stop it please.
I have tried using active profiles but that doesnt fix the problem
#SpringBootApplication
#EntityScan({ "com.demo" })
public class Application implements ApplicationRunner {
#Autowired
private IncrementalLoadRepository repo;
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
#Override
public void run(ApplicationArguments args) throws Exception {
IncrementalLoad incrementalLoad = new IncrementalLoad("fred", Instant.now(), Instant.now(), Instant.now());
repo.save(incrementalLoad);
}
and the unit test........
#RunWith(SpringRunner.class)
#SpringBootTest(classes = { Application.class })
#ActiveProfiles("test")
public class IncrementalLoadServiceTest {
#Autowired
private IncrementalLoadService incrementalLoadService;
#Test
public void checkInitialRecords_incrementalLoad() {
List<IncrementalLoad> incrementalLoads = incrementalLoadService.list();
assertEquals(3, incrementalLoads.size());
}
So I think I found the solution. I created another #SpringBootApplication class in my test folders. Initially that failed but I believe thats because the entity scan annotation pointed to packages where my "production" #SpringBootApplication was. I moved that class up a level and it all seems to work ok now.
I have a Spring Boot application structure like this:
src/main/java
/main/Application.java
src/main/resource/
/application-context.xml
src/test/java
/main/TestApplication.java
src/test/resource/
/application-context-test.xml
When I start application by Run As Spring Boot Application or Run as Junit
Both application-context.xml and application-context-test.xml were loaded.
But I only want to load application-context.xml in running mode, and application-context-test.xml in testing mode.
The initialisers look like:
#ImportResource("classpath:application-context.xml")
public class Application{
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
#ImportResource("classpath:application-context-test.xml")
public class TestApplication{
public static void main(String[] args) {
SpringApplication.run(TestApplication.class, args);
}
}
but they do not work.
Both the XMLs are loaded. How can I resolve this?
Annotate TestApplication with :
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = TestApplication.class)
I have the standard Application class which runs a Spring batch ETL:
#SpringBootApplication
public class Application {
public static void main(String[] args) {
SpringApplication.run(Application.class, args);
}
}
with my Junit test doing something like:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class MyServiceTest {
#Autowired
MyService myService;
#Test
public void testInsertions() {
//do stuff with assertions
}
}
My problem is that when I execute the junit test, the application also kicks off the ETL then executes the test. How to prevent the application from running?
I think there are a lot of alternatives and it really depends on what you are trying to achieve.
One of the options would be to run your tests with a specific profile, like testing, and configure your ETLs (I'm assuming they are just jobs) to be configured based on some property or specific profile.
For example:
Testing class
#ActiveProfiles("testing")
#RunWith(SpringJUnit4ClassRunner.class)
#SpringBootTest
public class MyServiceTest {
...
}
Job/ETL classes
#Component
#Profile("!testing")
public class JobEtlService {
}
Hope it helps.
I am experiencing rather strange thing when using Spring Boot. Lets get with it.
I have an app which, when ran from spring-boot:run, loads perfectly fine and I can use my server. However, if I try to run tests (either via launching test from IntelliJ or via surefire plugin) context fails to load.
Issue lies within this class (only relevant part shown):
#RestController
#RequestMapping(
value = "/sa/revisions/"
)
#SuppressWarnings("unchecked")
class RevisionController {
#Autowired
// cant autowire this field
private RepositoryEntityLinks repositoryEntityLinks = null;
/* omitted */
}
And here is my main class:
#EnableAsync
#EnableCaching
#EnableAutoConfiguration
#EnableConfigurationProperties
#Import({
SecurityConfiguration.class,
DataConfiguration.class,
RestConfiguration.class
})
public class SpringAtomApplication {
#Autowired
private DataLoaderManager dataLoaderManager = null;
public static void main(String[] args) {
SpringApplication.run(SpringAtomApplication.class, args);
}
#Bean
public CacheManager cacheManager() {
final GuavaCacheManager manager = new GuavaCacheManager();
manager.setAllowNullValues(false);
return manager;
}
#PostConstruct
private void doPostConstruct() {
this.dataLoaderManager.doLoad();
}
}
As I said, application loads without an issue when ran normally, however when it comes to this simple test, everything falls apart:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = SpringAtomApplication.class)
public class SpringAtomApplicationTests {
#Test
public void contextLoads() {
}
}
Would appreciate any suggestion, because I'd love to start with testing it.
You should set SpringApplicationContextLoader in your test class:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(
classes = SpringAtomApplication.class,
loader = SpringApplicationContextLoader.class)
public class SpringAtomApplicationTests {
#Test
public void contextLoads() {
}
}
With that you can test non-web features (like a repository or a service) or start an fully-configured embedded servlet container and run your tests using MockMvc.
Reference: http://docs.spring.io/spring-boot/docs/current/api/org/springframework/boot/test/SpringApplicationContextLoader.html