Disable Spring #EnableScheduling in Junit tests - java

I want to disable #Schedule in Spring tests but i can`t find a way to do it.
I have tried to make different config class for test environment but tasks are still fired.
This is config:
#Configuration
#EnableTransactionManagement
#EnableScheduling
#ComponentScan({"de.package"})
#PropertySource(name="application.properties", value="classpath:application.properties")
public class PersistenceJPAConfig {
...
}
This is test emvironment config.Just removed #EnableScheduling annotation
#Configuration
#EnableTransactionManagement
#ComponentScan({"de.package"})
#PropertySource(name="application.properties", value="classpath:application.properties")
public class PersistenceJPATestConfig {
...
}
In test i use:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = { PersistenceJPATestConfig.class }, loader = AnnotationConfigContextLoader.class)
#FixMethodOrder(MethodSorters.NAME_ASCENDING)
public class GetArticlesTest {
...
}
But tasks are still fired when i run the test..Is there any way to stop executing tasks while running tests ?

As you're using #ComponentScan on the same package both time, it seems spring is loading the other configuration too.
You could use some profile to filter that, like adding this on your PersistenceJPATestConfig
#Profile("test")
add this annotation on your JUnit class so it will be executed with the "test" profile
#ActiveProfiles("test")
Edit :
Your main config should also be profiled so it is ignored when its profile is not active, so you should add another #Profile on the main config class with a different profile than "test"

Quick solution based on other answers(for spring boot users), just add below code to main configuration so that it wont run on test profiles and test cases! No other changes!
#Profile(!test)
public class Config{
......
}

Related

Cannot load #Configuration class in component test marked as #SpringBootTest

I am testing a functionality and has written a componentTest to ensure the component is working. The issue is when running the test #Configuration class is not loading for the test. Example:
TestClass:
#SpringBootTest(classes = Application.class)
public class ServiceTest{
//Do Something
}
#Configuration
public class ConfigurationClass{
#PostConstruct
public void doSomething(){
log.info("Test loading");
}
}
When running the application, I can see the logs printed on application startup. When I run the test, I don't see the logs printing from the ConfigurationClass. I tried using #ContextConfiguration(classes=ConfigurationClass.class) but no luck.
Practically , I want the configurationClass to be loaded before the tests are loaded.
When you run #SpringBootTest(classes = Application.class) with a specified class, its instructs the spring boot test engine to load only beans defined in Application.java which is supposed to (usually) be a class annotated with #Configuration annotation directly or indirectly.
If you want to just load the whole application context in the test, just use #SpringBootTest without any attributes. Now in this case it will scan packages up to one with #SpringBootConfiguration annotation (which presents on the class annotated with #SpringBootApplication and then will scan the packages down to load the configuration classes.
Of course you should make sure that the test will be able to find #SpringBootApplication class, for that you should put the test in the same package or beneath (of course the tests are in src/test/java as opposed to the src/main/java where you main class resides.

Minimizing classes to load for JUnit testing

Let's say I'm testing a repository :
#RunWith(SpringRunner.class)
#SpringBootTest
public class UserRepositoryTest {
#Test
(...)
#Test
(...)
}
I'm ok that spring loads other repositories, but I'm not ok it loads the embedded Tomcat, the services, the controllers, ... every time I launch one of these JUnit.
What is the simplest way to achieve this?
I've tried to put some inner #Configuration class with a #ComponentScan limited to my repository package but it didn't work (it was just ignored).
Use the annotation #DataJpaTest instead of #SpringBootTest. It only loads the persistence related part of Spring.
#RunWith(SpringRunner.class)
#DataJpaTest
public class UserRepositoryTest {
#Test
(...)
#Test
(...)
}
You will find a detailed solution here
If you have some usage of JdbcTemplate then take a look to this answer
It looks like there is not one single answer to this question.
Of course, for JPA repositories, Lore answer is the best : use #DataJpaTest (or #JdbcTest for my use case). But be also sure to use "#AutoConfigureTestDatabase(replace = Replace.NONE)" if your test data is in your database and not in some in-memory one.
Also there is a special chapter talking about this in Spring doc :
Spring Boot’s auto-configuration system works well for applications
but can sometimes be a little too much for tests. It often helps to
load only the parts of the configuration that are required to test a
“slice” of your application.
source : https://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-testing.html#boot-features-testing-spring-boot-applications-testing-autoconfigured-tests
But it doesn't show all you can/need to do.
For example, I had a smtpClientService to test.
To test this service, alone in its own layer, I had to do these specific adaptations (if I omit "#AutoConfigureWebClient", I won't get RestTemplateBuilder injected) :
#RunWith(SpringRunner.class)
#SpringBootTest
#AutoConfigureWebClient
public class smtpClientServiceTest {
#Autowired
SmtpClientService service;
#Configuration
#Import(SmtpClientConfig.class)
#ComponentScan(basePackageClasses = SmtpClientService.class)
static class TestConfiguration {
}
#Test
public void testSendMessage() {
(...)
}
}

Ignore component scan when all tests are ignored

Is there a way to ignore component scan when all tests are ignored ?
Let's say I have test like this and all tests in class are ignored
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {TestConfig.class})
#WebAppConfiguration
public class ReqMigration {
//.... all tests are ignored
}
TestConfig.class looks like this
#Configuration
#PropertySource(value = "file:${path.app}/configuration/env.properties", ignoreResourceNotFound=true)
#PropertySource(value= "classpath:migration-test.properties")
#Import({BpmConfig.class, MonitorConfig.class})
#ActiveProfiles({"monitor-elasticsearch"})
public class TestConfig {
...
}
The problem is when I push such a test and run build in CI (Teamcity) it still tries to scan everything defined in TestConfig.class even all tests are ignored. Can I override somehow this behaviour ?

Override application.properties for integration tests in spring-boot app

I have a standard spring-boot app and I want to use MS SQL database for the production environment, whereas for integration tests I'd like to use h2 databse. The problem is that I wasn't able to find out, how to override the default application.properties file. Even though I was trying to follow some tutorials, I didn't come up with the right solution...maybe I'm just missing something...
The main class:
#SpringBootApplication
#EnableTransactionManagement
public class MyApplication {
public static void main(String[] args) {
SpringApplication.run(MyApplication .class, args);
}
}
and the class with tests:
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyApplication.class)
#WebIntegrationTest
public class MessageControllerTest {
#Autowired
MessageRepository messageRepository;
...
...
...
#Test
public void testSomething(){
...
...
...
...
}
}
So the question is, how to force the spring-boot to use application-test.properties file when running the tests, instead of application.properties, which should be used during the run time.
I tried for example to replace #WebIntegrationTest annotation with #TestPropertySource(locations="classpath:application-test.properties"), but this results in java.lang.IllegalStateException: Failed to load ApplicationContext.
Assuming you have a application-test.properties file in your app.
I do it in two ways :
1.CLI JVM Args
mvn spring-boot:run -Drun.jvmArguments="-Dspring.profiles.active=test
add the application-test.properties as an active profile.
add the spring.profiles.active=test in the application.properties and it will load your application-test.properties file.
As you pointed to in your answer annotate a class test with a specific active profile ( which is not suitable when having a large test classes i think ) #ActiveProfiles("test")
Actually it was pretty easy...after several hours of trying, I've realized that I just needed to annotate my test class with #ActiveProfiles("test") annotation.
#ActiveProfiles("test")
#RunWith(SpringJUnit4ClassRunner.class)
#SpringApplicationConfiguration(classes = MyApplication.class)
#WebIntegrationTest
public class MessageControllerTest {
#Autowired
MessageRepository messageRepository;
...
...
...
#Test
public void testSomething(){
...
...
...
...
}
}

Junit Suites with Spring autowired elements

I have a collection of Junit test classes with an autowired element (Spring). If I execute each Junit test class separately, everything works ok.
#SpringApplicationConfiguration(classes = Application.class)
#WebAppConfiguration
public class TestClass {
#Autowired
MyController control;
#Test
public void geolocTest() throws Exception {
...
}
I want to create a "Test Suite", but if I execute the Test Suite, it looks like the autowired elements are "null", so every test fails.
#RunWith(Suite.class)
#Suite.SuiteClasses({
TestClass.class
})
public class TestSuit extends TestCase {
...
}
What can I do? Thanks
NOTE:
What I want is to execute a code before all test classes, and another code after all test classes. I think I need a Suite for this...
As mentioned, you should use:
#RunWith(SpringJUnit4ClassRunner.class)
You can use #Before, #After, #BeforeClass, #AfterClass.
First two will be executed before and after each test case in a given Test class.
Last two will be executed only once per given Test class.
Your tests should be atomic as much as possible, so if you have all Test cases mutually dependent on same data or order of execution, try to rewrite this first.
If you wish to share some application properties, the good thing, for auto wiring between all test cases, such as the urls to mocks, take a look at the Spring profiles.
You can then have production specific and test specific properties which will be injected based on the current profile.
Take a look at the example and official docs:
http://docs.spring.io/spring-boot/docs/current/reference/html/boot-features-profiles.html
http://www.mkyong.com/spring/spring-profiles-example/
#Configuration
#ComponentScan
#Profile("test")
#PropertySource(value = "classpath:/yourApp.properties")
public class TestConfiguration {
#Bean
public static PropertySourcesPlaceholderConfigurer propertySourcesPlaceholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
}
You can then injected shared properties from the file in your test classes like this:
#Value("${mock.url}")
private String mockUrl;
Your missing at least the following
#RunWith(SpringJUnit4ClassRunner.class)
on your TestClass.

Categories