java 测试 Spring MVC 注释映射

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/861089/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-29 14:06:38  来源:igfitidea点击:

Testing Spring MVC annotation mappings

javaspringspring-mvc

提问by Brandon Yarbrough

With Spring MVC, you can specify that a particular URL will handled by a particular method, and you can specify that particular parameters will map to particular arguments, like so:

使用 Spring MVC,您可以指定特定 URL 将由特定方法处理,并且您可以指定特定参数将映射到特定参数,如下所示:

@Controller
public class ImageController {

   @RequestMapping("/getImage")
   public String getImage( @RequestParam("imageId") int imageId, Map<String,Object> model ) {
      model.put("image",ImageService.getImage(imageId));
   }

}

This is all well and good, but now I want to test that an http request with an imageId parameter will invoke this method correctly. In other words, I want a test that will break if I remove or change any of the annotations. Is there a way to do this?

这一切都很好,但现在我想测试带有 imageId 参数的 http 请求是否会正确调用此方法。换句话说,如果我删除或更改任何注释,我想要一个测试会中断。有没有办法做到这一点?

It is easy to test that getImage works correctly. I could just create an ImageController and invoke getImage with appropriate arguments. However, this is only one half of the test. The other half of the test must be whether getImage() will be invoked by the Spring framework when an appropriate HTTP request comes in. I feel like I also need a test for this part, especially as my @RequestMappingannotations become more complex and invoke complex parameter conditions.

很容易测试 getImage 是否正常工作。我可以创建一个 ImageController 并使用适当的参数调用 getImage 。然而,这只是测试的一半。另一半的测试一定是getImage()在合适的HTTP请求进来时是否会被Spring框架调用。 我觉得这部分我也需要测试一下,尤其是我的@RequestMapping注解变得越来越复杂,调用了复杂的参数条件。

Could you show me a test that will break if I remove line 4, @RequestMapping("getImage")?

如果我删除第 4 行,你能告诉我一个会中断的测试@RequestMapping("getImage")吗?

采纳答案by Oliver Drotbohm

You could use AnnotationMethodHandlerAdapterand its handlemethod programmatically. This will resolve the method for the given request and execute it. Unfortunately this is a little indirect. Actually there is a private class called ServletHandlerMethodResolverin AMHA that is responsible for just resolving the method for a given request. I just filed a request for improvementon that topic, as I really would like to see this possible, too.

您可以以编程方式使用AnnotationMethodHandlerAdapter及其handle方法。这将解析给定请求的方法并执行它。不幸的是,这有点间接。实际上,ServletHandlerMethodResolver在 AMHA 中有一个私有类,它负责解析给定请求的方法。我刚刚提交了关于该主题的改进请求,因为我也非常希望看到这成为可能。

In the meantime you could use e.g. EasyMockto create a mock of your controller class, expect the given method to be invoked and hand that mock to handle.

与此同时,您可以使用例如EasyMock来创建您的控制器类的模拟,期望调用给定的方法并将该模拟交给handle.

Controller:

控制器:

@Controller
public class MyController {

  @RequestMapping("/users")
  public void foo(HttpServletResponse response) {

    // your controller code
  }
}

Test:

测试:

public class RequestMappingTest {

  private MockHttpServletRequest request;
  private MockHttpServletResponse response;
  private MyController controller;
  private AnnotationMethodHandlerAdapter adapter;


  @Before
  public void setUp() {

    controller = EasyMock.createNiceMock(MyController.class);

    adapter = new AnnotationMethodHandlerAdapter();
    request = new MockHttpServletRequest();
    response = new MockHttpServletResponse();
  }


  @Test
  public void testname() throws Exception {

    request.setRequestURI("/users");

    controller.foo(response);
    EasyMock.expectLastCall().once();
    EasyMock.replay(controller);

    adapter.handle(request, response, controller);

    EasyMock.verify(controller);
  }
}

Regards, Ollie

问候, 奥利

回答by scarba05

Ollie's solution covers testing the specific example of an annotation but what about the wider question of how to test all the other various Spring MVC annotations. My approach (that can be easily extended to other annotations) would be

Ollie 的解决方案涵盖了对注解的特定示例的测试,但更广泛的问题是如何测试所有其他各种 Spring MVC 注解。我的方法(可以很容易地扩展到其他注释)将是

import static org.springframework.test.web.ModelAndViewAssert.*;

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({/* include live config here
    e.g. "file:web/WEB-INF/application-context.xml",
    "file:web/WEB-INF/dispatcher-servlet.xml" */})
public class MyControllerIntegrationTest {

    @Inject
    private ApplicationContext applicationContext;

    private MockHttpServletRequest request;
    private MockHttpServletResponse response;
    private HandlerAdapter handlerAdapter;
    private MyController controller;

    @Before
    public void setUp() {
       request = new MockHttpServletRequest();
       response = new MockHttpServletResponse();
       handlerAdapter = applicationContext.getBean(HandlerAdapter.class);
       // I could get the controller from the context here
       controller = new MyController();
    }

    @Test
    public void testFoo() throws Exception {
       request.setRequestURI("/users");
       final ModelAndView mav = handlerAdapter.handle(request, response, 
           controller);
       assertViewName(mav, null);
       assertAndReturnModelAttributeOfType(mav, "image", Image.class);
    }
}

I've also written a blog entry about integration testing Spring MVC annotations.

我还写了一篇关于集成测试 Spring MVC annotations博客条目