Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Mock service in Spring MVC

I have a problem with mocking service in Spring MVC:

@Controller
public class CompanyController {

  @Autowired
  private CompanyService companyService;

  @Autowired
  private CompanyRelationService companyRelationService;

  @GetMapping({"/", "/companies"})
  public String displayCompanies(Model model) {
    model.addAttribute("company", new Company());
    List<Company> companies = companyService.findAll();
    model.addAttribute("companies", companies);
    return "companies";
  }
}

and test:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
public class CompanyTests {

@Autowired
private WebApplicationContext webApplicationContext;

@Mock
CompanyService companyServiceMock;

private MockMvc mockMvc;


@Before
public void setUp() {
    Mockito.reset(companyServiceMock);
    mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
    MockitoAnnotations.initMocks(this);
}


@Test
public void shouldListAllCompanies() throws Exception {
    Company company1 = new Company("company1", new Address());
    Company company2 = new Company("company2", new Address());

    when(companyServiceMock.findAll()).thenReturn(Arrays.asList(company1, company2));

    mockMvc.perform(get("/companies"))
            .andExpect(status().isOk())
            .andExpect(view().name("companies"))
            .andExpect(model().attribute("companies", hasSize(2)))
            .andExpect(model().attribute("companies", hasItem(
                    allOf(
                            hasProperty("name", is("company1")))
            )))
            .andExpect(model().attribute("companies", hasItem(
                    allOf(
                            hasProperty("name", is("company2"))
                    )
            )));

}
}

The question is why I get companies from real service instead of mock (company1, company2):

java.lang.AssertionError: Model attribute 'companies'
     Expected: a collection containing (hasProperty("name", is "company1"))
     but: hasProperty("name", is "company1") property 'name' was "companyFromRealService", 
     hasProperty("name", is "company1") property 'name' was "CompanyFromRealService2"

Updated Test class, removed setUp and changed @Bean into @MockBean, but remain @SpringBootTest and it works:

@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest
@AutoConfigureMockMvc
public class CompanyTests {

@MockBean
private CompanyService companyServiceMock;

@Autowired
private MockMvc mockMvc;

@Test
@WithMockUser(roles = "ADMIN")
public void shouldListAllCompanies() throws Exception {
    Company company1 = new Company("company1", new Address());
    Company company2 = new Company("company2", new Address());

    when(companyServiceMock.findAll()).thenReturn(Arrays.asList(company1, company2));

    mockMvc.perform(get("/companies"))
            .andExpect(status().isOk())
            .andExpect(view().name("companies"))
            .andExpect(model().attribute("companies", hasSize(2)))
            .andExpect(model().attribute("companies", hasItem(
                    allOf(
                            hasProperty("name", is("companyFromRealService1")))
            )))
            .andExpect(model().attribute("companies", hasItem(
                    allOf(
                            hasProperty("name", is("companyFromRealService2"))
                    )
            )));
}

}

like image 652
Helosze Avatar asked Nov 23 '25 22:11

Helosze


1 Answers

First of all, if you are just testing controller slice of your application, you should use @WebMvcTest annotation instead of @SpringBootTest (you can find more information here). You can use it like this : @WebMvcTest(CompanyController.class).

Secondly why are you getting into trouble with MockMvc in setUp() method? You can erase that setUp method as people suggest in comments and @Autowire MockMvc.

Finally, as you are using spring boot, it is better to use @MockBean instead of @Mock which is a wrapped version of it inside the spring library.

like image 133
barbakini Avatar answered Nov 25 '25 12:11

barbakini