Search code examples
spring-bootjunitmockitospring-testspring-test-mvc

How to access a filed(or its getter and setter) in a RestController in Junit WebMvcTest?


Currently I'm writing unit tests for a spring boot application using Junit and Mockito. The problem I've encountered recently is that we have a RestController class which has some fields.

some of the fields are injected thorough Constructor and can be mocked.

but I have a private field which is not initialize using constructor and can be initialize only using setter method.

let's have a look at the code :

@RequestMapping("/api/directory")
public class DirectoryController {
     private final DirectoryService service;
     private ScheduledFuture future;

     public ScheduledFuture getFuture() {
        return future;
    }

    public void setFuture(ScheduledFuture future) {
        this.future = future;
    }

    public DirectoryController (DirectoryService service) {
        this.service = service;
    }


    @GetMapping(value = "/sync")
    public String sync(){
       if(getFuture() == null) throw new RuntimeException();

       // do some work

    }
  
}

Here "ScheduledFuture future" should be initilize using its setter method. Now, I Cannot write a proper WebMvcTest for a sync() in this class(in which we use future field). because future is null and the method will throw an exception unless I initilize it somehow.

but I don't know how to do that.

Any help will be appreciated.


Solution

  • Nothing stops you from calling the setter manually.

    Let's assume you have a test like the following:

    @WebMvcTest(DirectoryController.class)
    class YourTest{
        @Autowired
        private MockMvc mockMvc;
        @Test
        void testSync() throws Exception{
            mockMvc
                .perform(get("/api/directory/sync"))
                .andExpect(status().isOK());
            //some other checks
        }
    
    }
    

    You can just autowire the controller, create your mock object and then call the setter before making the request:

    @WebMvcTest(DirectoryController.class)
    class YourTest{
        @Autowired
        private MockMvc mockMvc;
        @Autowired
        private DirectoryController directoryController;//controller is autowired
        @Test
        void testSync() throws Exception{
            ScheduledFuture future = createYourMockObject();
            directoryController.setFuture(future);//HERE
            mockMvc
                .perform(get("/api/directory/sync"))
                .andExpect(status().isOK());
            //some other checks
        }
    
    }