我有一个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
,此测试失败。当我调试测试时,我看到当我的mockFoo
给new 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提到的那样在控制器中注入它们。