测试Spring MVC注释映射

Bra*_*ugh 19 java spring spring-mvc

使用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));
   }

}
Run Code Online (Sandbox Code Playgroud)

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

很容易测试getImage是否正常工作.我可以创建一个ImageController并使用适当的参数调用getImage.但是,这只是测试的一半.测试的另一半必须是当适当的HTTP请求进入时,Spring框架是否会调用getImage().我觉得我还需要对此部分进行测试,特别是当我的@RequestMapping注释变得更复杂并调用复杂参数时条件.

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

Oli*_*ohm 13

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

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

控制器:

@Controller
public class MyController {

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

    // your controller code
  }
}
Run Code Online (Sandbox Code Playgroud)

测试:

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);
  }
}
Run Code Online (Sandbox Code Playgroud)

此致,奥利


sca*_*a05 7

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);
    }
}
Run Code Online (Sandbox Code Playgroud)

我还写了一篇关于集成测试Spring MVC注释博客文章.