Search code examples
javaspring-bootjunitenvironment-variablesintegration-testing

Spring Boot Integration Test : Mock Environment Interface


In my Spring Security UserDetailsService, I inject Environment to read credentials from env variables. In an integration test, I would like to mock the Environment interface in order to change the env variables for the tests.

Here is my Test :

@ExtendWith(SpringExtension.class)
@SpringBootTest(classes = EportfolioApplication.class)
@AutoConfigureMockMvc
public class IntegrationAuth {
    @Autowired
    private MockMvc mockMvc;

    @Autowired
    private ObjectMapper objectMapper;

    @Test
    void loginCorrectCredentials_returnsToken() throws Exception {
        User user = new User();
        user.setUsername("John Shepard");
        user.setPassword("Tali");

        MvcResult mvcResult = mockMvc.perform(post("/login")
                .contentType("application/json")
                .content(objectMapper.writeValueAsString(user)))
                .andExpect(status().isOk())
                .andReturn();

        assertNotNull(
                "JWT Token should be present",
                mvcResult.getResponse().getHeader("Authorization")
        );
    }
}

What would be the best approach for this ?


Solution

  • You can use @TestPropertySource#properties. From its javadoc:

    Inlined properties in the form of key-value pairs that should be added to the Spring Environment before the ApplicationContext is loaded for the test. All key-value pairs will be added to the enclosing Environment as a single test PropertySource with the highest precedence.


    Here is a minimal example:

    @Service
    class MyService(
            environment: Environment
    ) {
        private val foo = environment["com.caco3.demo.foo"]
    
        fun getFoo() = foo
    }
    

    Test:

    @SpringBootTest
    @TestConstructor(autowireMode = TestConstructor.AutowireMode.ALL)
    @TestPropertySource(properties = ["com.caco3.demo.foo=test"])
    class ApplicationTest(
            private val service: MyService
    ) {
        @Test
        fun fooIsEqualToTest() {
            assertEquals("test", service.getFoo())
        }
    }