2009-05-14 6 views
18

, 당신은 특정 URL이 특정 방법으로 처리하도록 지정할 수 있으며, 특정 매개 변수과 같이, 특정 인수에 매핑되도록 지정할 수 있습니다테스트 스프링 MVC 주석 mapppings 스프링 MVC와

@Controller 
public class ImageController { 

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

} 

이를 모두 좋았지 만, 이제는 imageId 매개 변수가있는 http 요청이이 메소드를 올바르게 호출하는지 테스트하려고합니다. 즉, 주석을 제거하거나 변경하면 중단되는 테스트가 필요합니다. 이것을 할 수있는 방법이 있습니까?

getImage가 올바르게 작동하는지 테스트하기 쉽습니다. ImageController를 만들고 적절한 인수로 getImage를 호출 할 수 있습니다. 그러나 이것은 테스트의 절반에 불과합니다. 테스트의 나머지 절반은 적절한 HTTP 요청이 들어올 때 getImage()가 Spring 프레임 워크에 의해 호출 될지 여부 여야합니다. 특히 @RequestMapping 주석이 더 복잡해지고 복잡해지기 때문에이 부분에 대한 테스트가 필요합니다. 매개 변수 조건.

라인 4를 제거하면 작동하지 않을 테스트를 표시 할 수 있습니까? @RequestMapping("getImage")?

+1

질문을 완전히 이해하지 못했습니다. 어노테이션 매핑을 사용하는 Spring MVC 컨트롤러에 대한 유닛 테스트를 만드는 방법 "을 의미합니까? –

+0

죄송합니다. 주석이 정확하다는 것을 테스트하고, HTTP 요청이 실제로이 메소드를 호출한다는 것을 의미합니다. –

답변

12

AnnotationMethodHandlerAdapter 및 해당 handle 메서드를 프로그래밍 방식으로 사용할 수 있습니다. 그러면 주어진 요청에 대한 메소드가 분석되고 실행됩니다. 불행히도 이것은 약간 간접적입니다. 실제로는 AMHA에 ServletHandlerMethodResolver이라는 개인 클래스가 있으며, 이는 주어진 요청에 대한 메소드를 해석하는 역할을합니다. 나는이 주제에 request for improvement을 제출했다. 나는이 또한 가능한 것을보고 싶다.

예를 들어, EasyMock 컨트롤러 클래스의 모의 객체를 생성하려면 주어진 메소드가 호출 될 것으로 기대하고 그 모의 객체를 handle으로 전달하십시오.

컨트롤러 :

@Controller 
public class MyController { 

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

    // your controller code 
    } 
} 

테스트 :

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

감사합니다, 올리

+0

추가 행을 추가하십시오 :'request.setAttribute (HandlerMapping.INTROSPECT_TYPE_LEVEL_MAPPING, Boolean.TRUE);'컨트롤러 레벨 맵핑을 사용할 때 필요합니다. – takacsot

6

올리의 솔루션은 테스트하는 방법의 폭 넓은 질문에 대한 특정 주석의 예를하지만 테스트 커버 다른 모든 다양한 MVC 주석. (쉽게 다른 주석으로 확장 될 수있다) 나의 접근 방식은 내가 또한 blog entry about integration testing Spring MVC annotations를 작성했습니다

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

될 것이다.