【问题标题】:Spring MVC testing mapping with RedirectAttribute使用 RedirectAttribute 的 Spring MVC 测试映射
【发布时间】:2012-06-28 06:59:34
【问题描述】:

我的问题与这些类似:

但是

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

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.

其实我知道这个问题并且知道如何通过正确设置spring而不是在单元测试中来解决。

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

附加信息

基础设置模拟:

  @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)

【问题讨论】:

    标签: java spring spring-mvc mockito


    【解决方案1】:

    也许我遗漏了有关您的问题的一些信息,但我不明白您为什么要创建控制器的模拟来测试它...我想 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-06
      • 2019-07-11
      • 2012-08-14
      • 2016-03-13
      • 1970-01-01
      • 1970-01-01
      • 2018-08-05
      • 2019-11-01
      • 1970-01-01
      相关资源
      最近更新 更多