I have a Junit test running flawlessely within a Spring application context. The application context includes two xml files as well as an initializer. The JUnit base class is as follows:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration( locations = { "classpath:/applicationContext.xml",
"classpath:/applicationcontext-security.xml"},
initializers = com.abc.ConfigurationInitializer.class )
#TransactionConfiguration
#Transactional
public abstract class BaseTest extends AbstractTransactionalJUnit4SpringContextTests
{......
However when running the test under maven the application context fails to load and this is because the initializer class is not run.
Why is the Initializer(s) class not being run?
My bad - The initializer ran it simply crashed very soon thereafter
Related
Spring Boot related issue:
My application MyApp was based on MQ so I also wrote my tests to fit it.
Now, I have changed the application to work with Kafka instead of MQ.
My tests load up classes as part of the ApplicationContext list in the beginning of each test.
#RunWith( SpringJUnit4ClassRunner.class )
#ContextConfiguration(classes = {MyApp.class, Application.class, AppProperties.class, ...)
......
public class MyAppMainTest{
...
I have created and added few classes that related to Kafka: Producer, Properties, Client that I #Autowire inside my main class - MyApp.
#Component
public class MyApp {
#Autowired
private MyAppKafkaProducer myAppKafkaProducer;
#Autowired
private MyAppKafkaClient myAppKafkaClient;
I have added these Kafka clases to the ApplicationContext of MyAppMainTest.
#RunWith( SpringJUnit4ClassRunner.class )
#ContextConfiguration(classes = {MyAppKafkaClient.class, MyAppKafkaProducer.class, MyApp.class, ...)
....
public class MyAppMainTest {
MyAppMainTest does not test anything that related to Kafka, so basically they are useless in the test class.
The problem is that now, when the test loads up, it loads also the kafka class (because I have added them to the ApplicationContext because of the #Autowire inside the class itself), and when they loadup, they try to create a Kafka connection with localhost and then the whole test fails.
Is there any way to ignore (=not to load up) classes that exist inside the ApplicationContext list? I mean I understand that the whole point of ApplicationContext is to load up these classes and each related class, especially if its #Autowired, but in my case, they are not require inside the test class, and they cause it to fail.
So is there any way to ignore them although it's #Autowire?
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.
I have code that can be run properly as a JUnit test case. However, when I put the same test code inside a main class, spring configuration do not properly load the objects.
Spring code looks like this:
#ContextConfiguration(locations = { "classpath:/fileonly-sens-services.xml" })
#RunWith(SpringJUnit4ClassRunner.class)
public class AppTest extends ContextBuilder {
#BeforeClass
public static void setup() {
System.setProperty("app-
init.properties","classpath:test.app.properties");
#Test
someTestMethod()
}
I think it is a very simple problem but I cannot get it working outside of JUnit! Thanks for the help!
In your application you will have to create an ApplicationContext. The specifics of how to do it, depends on what kind of application you are building.
If you are building a command-line application, you can instantiate ClassPathXmlApplicationContext and use it to instantiate needed beans.
If you are building a web application, you can use ContextLoaderListener to load context during your application initialization.
I wrote two unit test classes using JUnit4. They both run fine separately, but running them one after another (by for example mvn test), the second test fails.
The reason the second test fails is because the first test modified a bean in the first test. The second test wants to use a fresh instance of this bean.
A unit test should be given a new Context for each unit test class. Spring has first-class support for context caching which I would like to disable. How can I configure Spring to restart a new Context for each unit test class?
My test classes are configured as such:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(locations = "classpath:a.context.xml")
public class AUnitTest {
#Test
public void someTestMethod{
doSomeFancyStuff();
}
}
You can use #DirtiesContexton a test method (or a test class). The Spring ApplicationContext will be reloaded after the execution of the test.
You can also use Mockito.reset() after you test.
This will save you the loading time of the Spring context.
In my application I initialize a property before spring application startup as follows:
MapLookup.setMainArguments(new String[] {"logging.profile", profile}); //from args
SpringApplication.run(source, args);
(just for reference: it is used for log4j2 logging, which must be set before spring starts to initialize).
Now I want to run an #IntegrationTest, but use the same logging configuration. Obviously I cannot use the code above, as a JUnit test is not executed using SpringApplication.run.
So, how could I initialize code before a #RunWith(SpringJUnit4ClassRunner.class) starts?
Note: BeforeClass does not work as this is executed after spring context startup.
You can run the initialization in a static initializer. Static initializer will run after JUnit loads the test class and before JUnit reads any annotations on it.
Alternatively you can extend SpringJUnit4ClassRunner with your own Runner initialize in it first and then run SpringJUnit4ClassRunner
I had a slightly different problem. I need to deploy something to my service after the Spring context is loaded. Solution use a custom config class for the test and run the deployment within a #PostConstruct Method.
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = TestConfig.class, loader = AnnotationConfigContextLoader.class)
public class JunitTest {
#Configuration
#ComponentScan(basePackages = { "de.foo })
public static class TestMConfig {
#Autowired
private DeploymentService service;
#PostConstruct
public void init() {
service.deploy(...);
}
}
#Test
public void test() {
...
}
}
Maybe this helps, someone, sometime, somewhere ;)