当方法使用ObjectMapper.writeValueAsString时,如何用mock编写单元测试



我有一个SpringMVC项目。我想测试的FooController的方法是:

@GetMapping("/view/{fooId}")
public String view(@PathVariable String fooId, Model model) throws FooNotFoundException, JsonProcessingException {
    Foo foo = fooService.getFoo(fooId);
    model.addAttribute("fooId", foo.getId());
    model.addAttribute("foo", new ObjectMapper().writeValueAsString(foo));
    return "foo/view";
}

我写的测试是:

public class FooControllerTest {
    @Mock
    private Foo mockFoo;
    @Mock
    private FooService mockFooService;
    @InjectMocks
    private FooController controller;
    private MockMvc mockMvc;
    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        mockMvc = MockMvcBuilders.standaloneSetup(controller).build();
    }
    @Test
    public void testView() throws Exception {
        String fooId = "fooId";
        when(mockFooService.getFoo(fooId)).thenReturn(mockFoo);
        when(mockFoo.getId()).thenReturn(fooId);
        mockMvc.perform(get("/foo/view/" + fooId))
                .andExpect(status().isOk())
                .andExpect(model().attribute("fooId", fooId))
                .andExpect(model().attributeExists("foo"))
                .andExpect(forwardedUrl("foo/view"));
    }
}

对于java.lang.AssertionError: No ModelAndView found,此测试失败。当我调试测试时,我看到当我的mockFoonew ObjectMapper.writeValueAsString()时它出错了。所以我认为模拟对象不能被序列化。我如何解决这个问题,如何让我的测试通过?


我已经试过了:

  • 我在FooController中注释了model.addAttribute("foo", new ObjectMapper().writeValueAsString(foo));行,这样测试就工作了(但不是我想要我的方法工作的方式)!现在我知道问题出在哪里了。
  • 我在FooControllerTest中注释了.andExpect(model().attributeExists("foo"))行,它仍然产生了上面的AssertionError。
  • 谷歌和stackoverflow,但我可以找到一些可用的。

一个同事建议如下:不使用mockFoo,创建一个新的Foo对象,并像这样使用它:

@Test
public void testView() throws Exception {
    String fooId = "fooId";
    Foo foo = new Foo(fooId);
    when(mockFooService.getFoo(fooId)).thenReturn(foo);
    mockMvc.perform(get("/foo/view/" + fooId))
            .andExpect(status().isOk())
            .andExpect(model().attribute("fooId", fooId))
            .andExpect(model().attributeExists("foo"))
            .andExpect(forwardedUrl("foo/view"));
}

这工作。我一直认为你必须模拟你没有测试的每一个对象(所以在控制器中,你模拟除了控制器本身之外的所有东西)。但是因为Foo是一个简单的POJO,所以不需要模拟它。

尝试在这样做InjectMocks注释时添加Spy注释

@InjectMocks
@Spy
private FooController controller;

是的,不要实例化ObjectMapper或控制器内的任何类。如果这样做,您将被迫使用PowerMockito。试着像@Ruben提到的那样在控制器中注入它们。

相关内容

  • 没有找到相关文章

最新更新