Don Rhummy
Don Rhummy

Reputation: 25830

Why does @InjectMocks controller's response get turned into empty by Mockito when I use @JsonView?

I am getting an empty json {} (verified via actions.andReturn().getResponse().getContentAsString()) as a response when I test via mockMvc.perform(post...)) despite the method actually returning a response (I see this when I debug and step through the code. It's a valid, filled response object but suddenly becomes null when some code in mockito is making a modalAndView -why does it do this?).

Test class:

@RunWith(MockitoJUnitRunner.class)
public class Test
{
    //Also tried @Mock
    @InjectMocks
    private MyService myService;

    @Mock
    private MyDAO myDAO;

    //@Autowired
    @InjectMocks
    private MyController myController;

    @Before
    public void setup() {

        //Build the controller mock handler
        mockMvc = MockMvcBuilders
            .standaloneSetup(myController)
            .setControllerAdvice(new ExceptionHandler())
            .build();
    }

    @org.junit.Test
    public void testMyEndpoint() throws Exception
    {
        //Make a request object
        MyRequest request = readJson("request.json", MyRequest.class );

        List<MyObject> objects = readJson("data.json", MyObject.class );

        Mockito.when(
            myDAO.getData( request )
        ).thenReturn(objects);

        Mockito.when(
            myService.callDAO(request)
        )
            .thenReturn(objects)

        //Call the aum endpoint
        ResultActions actions = mockMvc.perform(
            post( "/v1/endpoint" )
                .contentType(MediaType.APPLICATION_JSON)
                .content( new ObjectMapper().writeValueAsString( request ) )
        );

        //Why is this empty?
        System.out.println( actions.andReturn().getResponse().getContentAsString() );
    }
}

Upvotes: 0

Views: 872

Answers (1)

Don Rhummy
Don Rhummy

Reputation: 25830

Mockito uses an ObjectMapper that does not understand @JsonView. To get around this you need to set a message converter that does.

@RunWith(MockitoJUnitRunner.class)
public class Test
{
    //Also tried @Mock
    @InjectMocks
    private MyService myService;

    @Mock
    private MyDAO myDAO;

    //@Autowired
    @InjectMocks
    private MyController myController;

    /**
     * This is required for JsonViews.
     * @return
     */
    public static MappingJackson2HttpMessageConverter createJacksonConverter() {
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.configure(MapperFeature.DEFAULT_VIEW_INCLUSION, true);

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setObjectMapper(objectMapper);
        return converter;
    }

    @Before
    public void setup() {

        //Build the controller mock handler
        mockMvc = MockMvcBuilders
            .standaloneSetup(myController)
            .setControllerAdvice(new ExceptionHandler())
            .setMessageConverters(createJacksonConverter())
            .build();
    }

    @org.junit.Test
    public void testMyEndpoint() throws Exception
    {
        //Make a request object
        MyRequest request = readJson("request.json", MyRequest.class );

        List<MyObject> objects = readJson("data.json", MyObject.class );

        Mockito.when(
            myDAO.getData( request )
        ).thenReturn(objects);

        Mockito.when(
            myService.callDAO(request)
        )
            .thenReturn(objects)

        //Call the aum endpoint
        ResultActions actions = mockMvc.perform(
            post( "/v1/endpoint" )
                .contentType(MediaType.APPLICATION_JSON)
                .content( new ObjectMapper().writeValueAsString( request ) )
        );

        //Why is this empty?
        System.out.println( actions.andReturn().getResponse().getContentAsString() );
    }
}

Upvotes: 4

Related Questions