使用RedirectAttribute进行Spring MVC测试映射

时间:2012-06-28 06:59:35

标签: java spring spring-mvc mockito

我的问题与此类似:

BUT

给定控制器方法签名:

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.method.HandlerMethod     在org.springframework.web.servlet.mvc.method.AbstractHandlerMethodAdapter.handle(AbstractHandlerMethodAdapter.java:80)

1 个答案:

答案 0 :(得分:0)

也许我对你的问题遗漏了一些内容,但我不明白为什么你要创建一个模拟你的控制器来测试它...我想那个春天尝试用反射在你的类控制器上读取注释但是我无法正确使用模拟中的反射。

我认为这不是测试映射的正确方法。 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”处理。如果你需要一些mock,它应该在你的类AddNotificationController中。因此,在此类上使用@InjectMock并在此处创建控制器juste中使用的@Mock对象。我认为,这应该可以正常工作:

@Mock
public SomeService service;

@InjectMocks
public AddNotificationController controller = new AddNotificationController();

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

PS:对不起我的英语。