Mockito验证post对象具有相同的值而不是相同的对象引用

时间:2015-09-27 16:25:16

标签: spring-mvc mockito

这是我的测试:

    @Test
    public void shouldProcessRegistration() throws Exception {
        Spitter unsaved = new Spitter("Gustavo", "Diaz", "gdiaz", "gd123");
        Spitter saved = new Spitter(24L, "Gustavo", "Diaz", "gdiaz", "gd123");
        SpitterRepository spittlerRepository = Mockito.mock(SpitterRepository.class);
        Mockito.when(spittlerRepository.save(unsaved)).thenReturn(saved);

        SpitterController spittleController = new SpitterController(spittlerRepository);

        MockMvc mockSpittleController = MockMvcBuilders.standaloneSetup(spittleController).build();

        mockSpittleController.perform(MockMvcRequestBuilders.post("/spitter/register")
                .param("firstName", "Gustavo")
                .param("lastName", "Diaz")
                .param("userName", "gdiaz")
                .param("password", "gd123"))
                .andExpect(MockMvcResultMatchers.redirectedUrl("/spitter/" + saved.getUserName()));

        Mockito.verify(spittlerRepository, Mockito.atLeastOnce()).save(unsaved);
    }

这是我的控制者:

@Controller
@RequestMapping(value = "spitter")
public class SpitterController {
    SpitterRepository spitterRepository;

    @Autowired
    public SpitterController(SpitterRepository spittlerRepository) {
        this.spitterRepository = spittlerRepository;
    }

    @RequestMapping(value = "/register", method = RequestMethod.POST)
    public String processRegistration(Spitter spitter){
        spitterRepository.save(spitter);

        return "redirect:/spitter/" + spitter.getUserName();
    }
}

我想验证spitterRepository.save是否被调用,传递了我在测试中定义的相同unsaved对象。但我得到了这个例外:

Argument(s) are different! Wanted:
spitterRepository.save(
    spittr.Spitter@3bd82cf5
);
-> at spitter.controllers.test.SpitterControllerTest.shouldProcessRegistration(SpitterControllerTest.java:48)
Actual invocation has different arguments:
spitterRepository.save(
    spittr.Spitter@544fa968
);

3 个答案:

答案 0 :(得分:1)

如果我理解正确,下面的行初始化了一个模拟,你可以利用Spring中的功能。

MockMvc mockSpittleController = MockMvcBuilders.standaloneSetup(spittleController).build();

当您调用下面的模拟时,您不会使用unsaved对象调用该方法。相反,我想会创建一个新对象。

mockSpittleController.perform(MockMvcRequestBuilders.post("/spitter/register")
          .param("firstName", "Gustavo")
          .param("lastName", "Diaz")
          .param("userName", "gdiaz")
          .param("password", "gd123"))
          .andExpect(MockMvcResultMatchers.redirectedUrl("/spitter/" + saved.getUserName()));

这使得验证失败,因为实例将不相同。

要解决此问题,您应确保Spitter实施equals(),然后使用eq()匹配器进行验证:

Mockito.verify(spittlerRepository, Mockito.atLeastOnce()).save(org.mockito.Matchers.eq(unsaved));

这将检查预期的参数equals()是否传递了什么。

答案 1 :(得分:1)

使用ArgumentCaptor捕获传递给save的值,然后对其进行断言。

ArgumentCaptor<Spitter> spitterArgument = ArgumentCaptor.forClass(Spitter.class);
verify(spittlerRepository, atLeastOnce()).save(spitterArgument.capture());

assertEquals("Gustavo", spitterArgument.getValue().getName());

如果Bean是相同的断言,我建议你使用Hamcrest的samePropertyValues(http://hamcrest.org/JavaHamcrest/javadoc/1.3/org/hamcrest/beans/SamePropertyValuesAs.html

答案 2 :(得分:0)

import org.mockito.Matchers;
//...
Mockito.verify(spittlerRepository, Mockito.atLeastOnce()).save(Matchers.refEq(unsaved));