4

I have a Spring MVC REST controller class that has a private instance boolean field injected via @Value ,

@Value("${...property_name..}")
private boolean isFileIndex;

Now to unit test this controller class, I need to inject this boolean.

How do I do that with MockMvc?

I can use reflection but MockMvc instance doesn't give me underlying controller instance to pass to Field.setBoolean() method.

Test class runs without mocking or injecting this dependency with value always being false. I need to set it to true to cover all paths.

Set up looks like below.

@RunWith(SpringRunner.class)
@WebMvcTest(value=Controller.class,secure=false)
public class IndexControllerTest {

    @Autowired
    private MockMvc mockMvc;
 ....
}
Sabir Khan
  • 9,826
  • 7
  • 45
  • 98

2 Answers2

5

You can use @TestPropertySource

@TestPropertySource(properties = {
    "...property_name..=testValue",
})
@RunWith(SpringRunner.class)
@WebMvcTest(value=Controller.class,secure=false)
public class IndexControllerTest {

    @Autowired
    private MockMvc mockMvc;

}

You can also load your test properties form a file

@TestPropertySource(locations = "classpath:test.properties")

EDIT: Some other possible alternative

@RunWith(SpringRunner.class)
@WebMvcTest(value=Controller.class,secure=false)
public class IndexControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @Autowired 
    private Controller controllerUnderTheTest;


    @Test
    public void test(){
        ReflectionTestUtils.setField(controllerUnderTheTest, "isFileIndex", Boolean.TRUE);

        //..
    }

}
Peter Jurkovic
  • 2,686
  • 6
  • 36
  • 55
  • 1
    so how to change property value for different `@Test` methods? This annotation is applicable at test class level.Primary target is not to get values from property file but to alter values for various scenarios. – Sabir Khan Jun 13 '17 at 09:58
  • @SabirKhan Then you should reload your application context with different test properties. But it should be possible also change it using reflection as is shown above. See updated post. – Peter Jurkovic Jun 13 '17 at 10:33
  • Yes, I had got it working with something like `controller = new IndexController(); mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); isFileIndexField = controller.getClass().getDeclaredField("isFileIndex"); isFileIndexField.setAccessible(true); indexServiceField = controller.getClass().getDeclaredField("indexService"); indexServiceField.setAccessible(true); indexServiceField.set(controller, indexService);` but your suggestion is pretty small code. – Sabir Khan Jun 13 '17 at 10:50
  • Your answer using `ReflectionTestUtils` is working and I didn't know that I can do - `@Autowired private Controller controllerUnderTheTest;` . Seems knowing that was the key. Thanks !! – Sabir Khan Jun 13 '17 at 10:52
  • Yes, you can. It is just a Spring bean. – Peter Jurkovic Jun 13 '17 at 11:04
0

My preferred option would be to set it in the constructor and annotate the constructor parameter with the @Value. You could then pass in whatever you want in the test.

See this answer

user1675642
  • 747
  • 2
  • 5
  • 15
  • I am not explicitly creating controller instance here so I think, constructor wouldn't help. Let me know if I am missing anything. – Sabir Khan Jun 13 '17 at 09:43