Spring: <util:properties> ignored in JUnit environment? - spring

In my Spring servlet configuration (lets call it service-servlet.xml) I am loading properties from a file:
<util:properties id="ServiceProperties" location="classpath:service.properties" />
And then later autowiring them in my service class:
#Value("#{ServiceProperties['my.property']}")
private Integer myProp;
This works fine and service runs with no problems when deployed under Glassfish.
Now I am writing a test class for my service, and running it with SpringJUnit4ClassRunner:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration({
"classpath:service-test-servlet.xml",
"classpath:service-test-context.xml"
})
public class ServiceTest {
// ...
}
So in service-test-servlet.xml, which is a copy of service-servlet.xml with few minor adjustments for testing environment, I do include the properties file the same way, but seems it is simply ignored...
First, I thought, I may be that my file is not found or so, but then even if I intentionally enter wrong name - it just ignores it and goes further with crashes at some later point because there is no bean named "ServiceProperties" and it cannot autowire "myProp" in my service class...
Is the <util:properties> being totally ignored in JUnit environment?

Related

Mock Bean for all JUnit Tests in Spring Boot

In Spring Boot, is there a way to mock a single bean for all existing JUnit tests, without changing the existing test classes (e.g., by adding an annotation or adding inheritance)? Like injecting a bean globally via configuration.
Assuming you are using #SpringBootApplication in your main sources to define the Spring Boot application, you'll already have component scanning enabled for everything in that package (including nested packages).
When running tests, the classes (typically) in src/test/java are also added to the classpath, and are therefore available to be scanned as well.
For example, if you defined your #SpringBootApplication at com.example.boot.MySpringBootApplication, then com.example.boot.MyTestConfiguration would be eligible for component scanning, even though the former is in src/main and the latter in src/test. Putting it in the src/test/java directory would ensure that it only has an effect while running tests.
You can then define any "global" beans you would like in that configuration.
Using the package/class names I provided:
// File: src/test/java/com/example/boot/MyTestConfiguration.java
#Configuration // this will get component-scanned
public class MyTestConfiguration {
#MockBean
MyBean myGlobalMockBean;
}
Then, so long as you don't omit that Configuration from the Context Configuration, the MockBean should always be present under test.

Are the project beans already instantiated when we try to run a junit test in spring boot

I am new to Spring and spring boot.
For my spring boot application which is a rest controller, I have some beans along with my data source.
I use my data source to create jdbc template. Now when I am in my rest controller code, I have all these beans #Autowired and they work perfectly fine.
My query is regarding the junit testing part.
When I write my test code inside src/test/java and when I execute my test class within IDE, are the beans defined in my src/main/javacode, instantiated before test case execution?
You might use the same container, or instantiate another container particularly for testing purposes, for which you'll provide a configuration of that other Spring Container separately:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:test-context.xml")
public class SomeClassTest{...}
However, you can also enable support for loading your Application Context and then use the #Autowired fields in your JUnit fixtures, which also works fine too:
#RunWith(SpringRunner.class)
public class SomeTestClass {
....
#Autowired
ApplicationContext context;
....
}
From here, you can get any bean you wish.

Configuration of SpringJUnit4ClassRunner Test clashes with SpringBootTest

I have a bunch of tests in my project that are all annotated with #SpringBootTest and therefore load up a SpringBoot context.
Now recently I refactored a Test in which I wanted a smaller scope (it´s about process coverage with camunda) to #RunWith(SpringJUnit4ClassRunner.class).
Since this means that no context is loaded automatically I create some beans "manually" with a static inner class configuration. The entire test looks something like this:
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration(classes = {
ExternalConfiguration.class, MyTest.InternalConfiguration.class
})
public class MyTest{
#Autowired
private SomeBean someInternalBean;
#Configuration
public static class InternalConfiguration{
#Bean
SomeBean someInternalBean() {
return mock(SomeBean .class);
}
}
//Tests
Now, this test runs fine when I run it. BUT when I run any other test ( those still annotated with #SpringBootTest), I get issues with when the ApplicationContext is loaded:
The bean 'someInternalBean', defined in class path resource [.../MyTest$InternalConfiguration.class], could not be registered. A bean with that name has already been defined in file [.../SomeBean.class] and overriding is disabled.
Apparently a bean is created when loading the ApplicationContext because the class is annotated with #Component AND the context loader tries to create another bean from my internal configuration.
I cant allow bean-overriding because my mock beans might overwrite the automatically created beans (which they do, I tried).
How do I circumvent this? I want my SpringJUnit4ClassRunner-tests with their internal configurations to not affect my other #SpringBootTest-tests. I already tried making the configuration beans conditional with #ConditionalOnMissingBean but that did not work.
Turns out those inner configuration classes should not be annotated with #Configuration. Removing the annotation makes it so that the manual bean generation still works and the configuration is no longer picked up by the componentScan.

removing singleton beans from context during the test

I have an application written using spring-REST(spring version 4.1.x and am using spring test for testing it. One of the singleton bean is caching the state so that it can be used for subsequent call in the application. This is although causing the problem when I am running multiple tests as the same bean is being used across tests and subsequent test fails. My question is how do I reset the state in the teardown?
State is not accessible as its a private member of the class. Can we just remove the bean completely from the context? I am using annotated beans and autowiring wherever required.
#RunWith(SpringJUnit4ClassRunner.class)
#WebAppConfiguration
#ContextConfiguration(classes = ComponentTestConfig.class)
public class WebServiceComponentTest {
}
I tried to use the solution given in the following link
How can i remove a singleton spring bean from ApplicationContext?
but always faiuls with no bean definition found
((BeanDefinitionRegistry) beanFactory).removeBeanDefinition("myBean");
By the way test fails only when teardown called for resetting the bean state. Bean is found while it is being used by application.
If you want more fine-grained control over your testing application context, mirror your XML config files for testing. Point your test class to only load the XML files from your test directory rather than from your WebContent directory.
That way you can totally exclude the class that is causing you problems from your test context. So your test XML might look something like this:
<context:component-scan base-package =
"au.com.foo.pineapple",
"au.com.foo.dolphin",
"au.com.foo.controllers"
/>
<!--au.com.foo.building-->
and your WebContent XML file might look something like this:
<context:component-scan base-package =
"au.com.foo.pineapple",
"au.com.foo.dolphin",
"au.com.foo.building",
"au.com.foo.controllers"
/>
As M. Deinum pointed out, the safest way to achieve this is to use the #DirtiesContext annotation.
However, as also mentioned, using #DirtiesContext can result in longer test runs since the ApplicationContext will be removed from the ContextCache.
Another option -- a hack really -- is to use the ReflectionTestUtils class from spring-test to change the state of the private member in question.
Regards,
Sam (author of the Spring TestContext Framework)

how to define contextParameter in Spring

I am working on a web project and I defined some properties in the context.xml of my Tomcat, like path, properties value for the configuration of the application.
My problem arrives when I want to write some JUnit tests, which are launched outside my web container, how can I define these parameters?
To be clear, in my context.xml (in Tomcat configuration directory), I have:
<Parameter name="myProperty" value="myValue" override="false"/>
And with Spring, I access it with:
<property name="property" value="#{myProperty}" />
But when I launch a junit test, the context.xml is not loaded, I need another way to define the property.
How can I do that?
To be more precise, the context.xml file which we are talking about is a file used by my Tomcat server, it does not follow the Spring schema and I think that I can't "import" it into Spring.
I already use the SpringJUnit4ClassRunner and the ContextConfiguration tag, it works fine, but now, I need to emulate/replace the Tomcat's behaviour to define this ContextParameters and retrieve my parameter...
I hope I am clearer :)
Try using something like this :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("classpath:context.xml")
public class MyTestClass {
//put tests here
}
EDIT:
You can also specify a path to the context file :
#RunWith(SpringJUnit4ClassRunner.class)
#ContextConfiguration("file:src/main/resources/spring/config.xml")
public class MyTestClass {
//put tests here
}
For the suggestion above to work, you need to depend on the spring-test module.
You can also load your context file the good old fashion way.
ApplicationContext context = new ClassPathXmlApplicationContext("context.xml")
And then grab your bean by name.

Resources