4

我的问题与这些类似:

给定一个控制器方法签名:

public String setupForm(
    @ModelAttribute("notification") Notification n, RedirectAttributes redirect)

并给出一个测试(使用 Mockito):

@Mock
private AddNotificationController handler;
@Test
public void get() throws Exception{
    request.setRequestURI("/addNotification/save.do");
    request.setMethod("GET");
    adapter.handle(request, response, handler);
    verify(handler,times(1)).setupForm(any(Notification.class), any(RedirectAttributes.class));
  }

执行时出现异常:

org.springframework.web.bind.annotation.support.HandlerMethodInvocationException: 
Failed to invoke handler method [public java.lang.String ep.rdp.web.AddNotificationController.setupForm(a.b.c.Notification,org.springframework.web.servlet.mvc.support.RedirectAttributes)]; 
nested exception is java.lang.IllegalStateException: 
Argument [RedirectAttributes] is of type Model or Map but is not assignable from the actual model. 
You may need to switch newer MVC infrastructure classes to use this argument.

实际上我知道问题并且知道如何通过正确设置弹簧而不是在单元测试中来解决。

所以问题是:我还必须在模拟中设置什么才能使其正常工作?

附加信息

基础设置模拟:

  @Before
  public void setup() {
//    adapter = new AnnotationMethodHandlerAdapter();
    adapter = new RequestMappingHandlerAdapter();
    request = new MockHttpServletRequest();
    /*
     * needed for AnnotationMethodHandlerAdapter when resolving controlle level mapping
     */
    request.setAttribute(HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, Boolean.TRUE);
    response = new MockHttpServletResponse();
  }

现实

  • 使用 AnnotationMethodHandlerAdapter 时出现此症状。
  • 当我使用 RequestMappingHandlerAdapter 我得到:

    java.lang.ClassCastException:ep.rdp.web.CacheController$$EnhancerByMockitoWithCGLIB$$d8aab2c0 不能在 org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter .java:80)

4

1 回答 1

0

也许我错过了有关您的问题的一些信息,但我不明白您为什么要创建控制器的模拟来对其进行测试...我想spring 尝试通过反射读取您的类控制器上的注释,但我不能使用正确地反思你的模拟。

我认为这不是测试映射的正确方法。Spring 提供了这个模块来对你的控制器进行单元测试,并且提供了一切。所以你不应该在这里创建任何模拟。如果你想在你的真实对象上模拟一个方法,也许是一个@Spy(一个应用于真实对象的间谍)。

你想要做的是创建这样的东西:

@Before
public void setUp() {
    this.mockMvc = MockMvcBuilders
            .standaloneSetup(new AddNotificationController())
            .build();
}

// and your test
@Test
public void testYourMethodName() {
    this.mockMvc.perform(MockHttpServletRequestBuilder.get("/addNotification/save.do"))
            .andExpect(MockMvcResultMatchers.status().isOk())
            .andExpect(MockMvcResultMatchers.handler().method("yourMethodName"))
            .abdExpect(MockMvcResultMatchers.redirectedUrl("yourUrl"));
}

如您所见,您没有使用 mockito 提供的任何模拟对象,但我仍然检查请求是由方法“yourMethodName”处理的事实。如果你需要一些模拟,它应该在你的类 AddNotificationController 中。因此,在此类上使用 @InjectMock 并在此处创建控制器内部使用的 @Mock 对象。我认为,这应该可以正常工作:

@Mock
public SomeService service;

@InjectMocks
public AddNotificationController controller = new AddNotificationController();

@Before
public void setUp() {
    this.mockMvc = MockMvcBuilders
            .standaloneSetup(this.controller)
            .build();
}

PS:对不起我的英语。

于 2014-02-01T18:49:13.023 回答