Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Should Mockito be used with MockMvc's webAppContextSetup in Spring 4?

I'm having difficulties getting Mockito and MockMvc working together when I use the webAppContextSetup together. I'm curious if it's because I'm mixing the two in a way they were never intended.

Source: https://github.com/zgardner/spring-boot-intro/blob/master/src/test/java/com/zgardner/springBootIntro/controller/PersonControllerTest.java

Here is the test I'm running:

package com.zgardner.springBootIntro.controller;

import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
import org.springframework.boot.test.SpringApplicationConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;

import static java.lang.Math.toIntExact;
import static org.hamcrest.Matchers.is;
import static org.mockito.MockitoAnnotations.initMocks;
import static org.mockito.Mockito.when;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.get;
import static org.springframework.test.web.servlet.result.MockMvcResultHandlers.print;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.webAppContextSetup;

import com.zgardner.springBootIntro.Application;
import com.zgardner.springBootIntro.service.PersonService;
import com.zgardner.springBootIntro.model.PersonModel;

@RunWith(SpringJUnit4ClassRunner.class)
@SpringApplicationConfiguration(classes = Application.class)
@WebAppConfiguration
public class PersonControllerTest {

    private MockMvc mockMvc;

    @Autowired
    private WebApplicationContext webApplicationContext;

    @Autowired
    private DefaultListableBeanFactory beanFactory;

    @Mock
    private PersonService personService;

    @InjectMocks
    private PersonController personController;

    @Before
    public void setup() {
        initMocks(this);

        // beanFactory.destroySingleton("personController");
        // beanFactory.registerSingleton("personController", personController);

        mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    }

    @Test
    public void getPersonById() throws Exception {
        Long id = 999L;
        String name = "Person name";

        when(personService.findById(id)).thenReturn(new PersonModel(id, name));

        mockMvc.perform(get("/person/getPersonById/" + id))
            .andDo(print())
            .andExpect(jsonPath("$.id", is(toIntExact(id))))
            .andExpect(jsonPath("$.name", is(name)));
    }
}

I was expecting that when mockMvc performed the mock of that HTTP call, it would use the PersonController I defined in my test. But when I debug through, it's using the PersonController which was created by the SpringJunit4ClassRunner on the test boot up.

I found two ways to get this to work:

  1. Inject the bean factory, remove the old personController singleton, and add my own. This is ugly, and I am not a fan.
  2. Wire everything up using the standaloneSetup instead of webAppContextSetup. I may do this instead as I don't have to touch the bean factory.

Here are some different articles I've found that somewhat touch on the topic:

  • Spring Tutorial - Building REST Services This just autowires in the repos to clear out the data before the integration test takes place.
  • Use Spring MVC Test framework and Mockito to test controllers This uses Mockito along with webAppContextSetup, but this is in Spring 3. (I'm using Spring Boot)
  • Unable to mock Service class in Spring MVC Controller tests This uses the standaloneSetup, which does work in my case too.

Thoughts?

like image 399
Zach Gardner Avatar asked Dec 13 '25 07:12

Zach Gardner


1 Answers

You might be interested in the new testing features coming in Spring Boot 1.4 (specifically the new @MockBean annotation). This sample shows how a service can be mocked and used with a controller test.

like image 177
Phil Webb Avatar answered Dec 14 '25 22:12

Phil Webb



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!