Reputation: 10464
I'm writing a few unit tests for a Spring application that can be run with two different configurations. The two different configurations are given by two application.properties
file. I need to write tests twice for each class, since I need to verify that changes that work with a configuration don't impact the other one.
For this reason I created two files in the directory:
src/test/resources/application-configA.properties
src/test/resources/application-configB.properties
Then I tried to load them using two different values of @TestPropertySource
:
@SpringBootTest
@TestPropertySource(locations = "classpath:application-configA.properties")
class FooTest {
@InjectMock
Foo foo;
@Mock
ExternalDao dao;
// perform test
}
And the Foo
class is this one:
@Service
public class Foo {
@Autowired
private External dao;
methodToTest() {
Properties.getExampleProperty();
this.dao.doSomething(); // this needs to be mocked!
}
}
While the class Properties
is:
@Component
public class Properties {
private static String example;
@Value("${example:something}")
public void setExampleProperty(String _example) {
example = _example;
}
public static String getExampleProperty() {
return example;
}
}
The problem is that Properties.getExampleProperty()
always returns null during the test, while it contains the correct value in the normal execution.
I've tried:
application.properties
application-configA.properties
of /mainapplication-configA.properties
of /testNothing of these worked.
I've read this question's answers, but looks like something different and they did not help me
Upvotes: 8
Views: 13263
Reputation: 10464
After many attempts, finally I found a solution. The problem was caused by using Spring 4 with JUnit 5, and even though it wasn't showing any warning or error, it wasn't able to load the Spring context. In all honesty, I don't know what @SpringBootTest
was doing in practice.
The solution was about adding the spring-test-junit5
dependency as stated in this answer, then the following steps:
@SpringBootTest
annotation@ExtendWith(SpringExtension.class)
, importing the class from spring-test-junit5
@Import(Properties.class)
Now the annotations for the test look like this:
@ExtendWith(SpringExtension.class)
@PropertySource("classpath:application-configA.properties")
@TestPropertySource("classpath:application-configA.properties")
@Import(Properties.class)
class FooTest {
Upvotes: 4
Reputation: 1306
I recommend using @Before
in order to set values in unit tests if it's for a whole class using org.springframework.test.util.ReflectionTestUtils
,
However in order to do so you will have to inject Properties
instance in test class
@InjectMocks Properties properties;
...
@Before
public void setUp() {
ReflectionTestUtils.setField(properties, "example", "something");
}
alternatively you can use same ReflectionTestUtil
in @Test
too - I think
update:
Your way of Using @TestPropertySource
is definitely correct but there might be some conflict on using terminology location
and properties
,
In my opinion I have see code doing,
@TestPropertySource(properties = "classpath:application-configA.properties")
Plus, have you tried adding @ActiveProfile('test')
and @AutoConfigureMockMvc
?
Upvotes: 0