[SPRING] @PathVariable을 사용하여 Spring MVC 컨트롤러를 단위 테스트하는 방법?
SPRING@PathVariable을 사용하여 Spring MVC 컨트롤러를 단위 테스트하는 방법?
나는 이것과 비슷한 간단한 주석 처리 된 컨트롤러를 가지고있다 :
@Controller
public class MyController {
@RequestMapping("/{id}.html")
public String doSomething(@PathVariable String id, Model model) {
// do something
return "view";
}
}
다음과 같은 단위 테스트로 테스트하고 싶습니다.
public class MyControllerTest {
@Test
public void test() {
MockHttpServletRequest request = new MockHttpServletRequest();
request.setRequestURI("/test.html");
new AnnotationMethodHandlerAdapter()
.handle(request, new MockHttpServletResponse(), new MyController());
// assert something
}
}
문제는 AnnotationMethodHandlerAdapter.handler () 메서드가 예외를 throw합니다.
java.lang.IllegalStateException: Could not find @PathVariable [id] in @RequestMapping
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter$ServletHandlerMethodInvoker.resolvePathVariable(AnnotationMethodHandlerAdapter.java:642)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolvePathVariable(HandlerMethodInvoker.java:514)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.resolveHandlerArguments(HandlerMethodInvoker.java:262)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:146)
해결법
-
==============================
1.Spring 3.2에서, 이것을 우아하고 쉬운 방법으로 테스트 할 수있는 적절한 방법이있다. 다음과 같은 일을 할 수 있습니다.
Spring 3.2에서, 이것을 우아하고 쉬운 방법으로 테스트 할 수있는 적절한 방법이있다. 다음과 같은 일을 할 수 있습니다.
@RunWith(SpringJUnit4ClassRunner.class) @WebAppConfiguration @ContextConfiguration("servlet-context.xml") public class SampleTests { @Autowired private WebApplicationContext wac; private MockMvc mockMvc; @Before public void setup() { this.mockMvc = webAppContextSetup(this.wac).build(); } @Test public void getFoo() throws Exception { this.mockMvc.perform(get("/foo").accept("application/json")) .andExpect(status().isOk()) .andExpect(content().mimeType("application/json")) .andExpect(jsonPath("$.name").value("Lee")); } }
자세한 내용은 http://blog.springsource.org/2012/11/12/spring-framework-3-2-rc1-spring-mvc-test-framework/에서 확인하십시오.
-
==============================
2.나는 Spring 레퍼런스 매뉴얼의 용어를 기반으로 통합 테스트를 한 후에 자신이하는 것을 호출 할 것이다. 방법에 대해 같은 일을 :
나는 Spring 레퍼런스 매뉴얼의 용어를 기반으로 통합 테스트를 한 후에 자신이하는 것을 호출 할 것이다. 방법에 대해 같은 일을 :
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 testDoSomething() throws Exception { request.setRequestURI("/test.html"); final ModelAndView mav = handlerAdapter.handle(request, response, controller); assertViewName(mav, "view"); // assert something } }
자세한 내용은 스프링 MVC 주석 통합 테스트에 대한 블로그 항목을 작성했습니다.
-
==============================
3.Spring MVC 테스트를위한 유망한 프레임 워크 https://github.com/SpringSource/spring-test-mvc
Spring MVC 테스트를위한 유망한 프레임 워크 https://github.com/SpringSource/spring-test-mvc
-
==============================
4.예외 메시지는 샘플 코드에없는 "피드"변수를 나타내며, 사용자가 표시하지 않은 것으로 인해 발생했을 수 있습니다.
예외 메시지는 샘플 코드에없는 "피드"변수를 나타내며, 사용자가 표시하지 않은 것으로 인해 발생했을 수 있습니다.
또한, 당신의 테스트는 Spring과 당신의 코드를 테스트하는 것입니다. 이게 정말로 당신이하고 싶은 일입니까?
Spring이 작동한다고 가정하는 것이 낫다. MyController.doSomething ()을 직접 호출한다. 이것이 주석 접근법의 한 가지 이점입니다. 모의 요청과 응답을 사용할 필요가 없으며 도메인 POJO 만 사용하면됩니다.
-
==============================
5.여기 스프링 테스트 -mvc가 아닌 스프링 테스트를 사용하여 Emil과 scarba05의 합병을 제안합니다. 이 답변을 건너 뛰고 Spring 3.2.x 이상을 사용하는 경우 spring-test-mvc 예제를 참조하십시오.
여기 스프링 테스트 -mvc가 아닌 스프링 테스트를 사용하여 Emil과 scarba05의 합병을 제안합니다. 이 답변을 건너 뛰고 Spring 3.2.x 이상을 사용하는 경우 spring-test-mvc 예제를 참조하십시오.
@Controller public class MyControllerWithParameter { @RequestMapping("/testUrl/{pathVar}/some.html") public String passOnePathVar(@PathVariable String pathVar, ModelMap model){ model.addAttribute("SomeModelAttribute",pathVar); return "viewName"; } }
import static org.springframework.test.web.ModelAndViewAssert.assertViewName; import java.util.HashMap; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.ApplicationContext; import org.springframework.mock.web.MockHttpServletRequest; import org.springframework.mock.web.MockHttpServletResponse; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.web.ModelAndViewAssert; import org.springframework.web.servlet.HandlerAdapter; import org.springframework.web.servlet.HandlerMapping; import org.springframework.web.servlet.ModelAndView; import org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = {"file:src\\main\\webapp\\WEB-INF\\spring\\services\\servlet-context.xml" }) public class MyControllerTest { private MockHttpServletRequest request; private MockHttpServletResponse response; private HandlerAdapter handlerAdapter; @Before public void setUp() throws Exception { request = new MockHttpServletRequest(); response = new MockHttpServletResponse(); this.handlerAdapter = applicationContext.getBean(AnnotationMethodHandlerAdapter.class); } // Container beans private MyControllerWithParameter myController; private ApplicationContext applicationContext; public ApplicationContext getApplicationContext() { return applicationContext; } @Autowired public void setApplicationContext(ApplicationContext applicationContext) { this.applicationContext = applicationContext; } public MyControllerWithParameter getMyController() { return myController; } @Autowired public void setMyController(MyControllerWithParameter myController) { this.myController = myController; } @Test public void test() throws Exception { request.setRequestURI("/testUrl/Irrelavant_Value/some.html"); HashMap<String, String> pathvars = new HashMap<String, String>(); // Populate the pathVariable-value pair in a local map pathvars.put("pathVar", "Path_Var_Value"); // Assign the local map to the request attribute concerned with the handler mapping request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathvars); final ModelAndView modelAndView = this.handlerAdapter.handle(request, response, myController); ModelAndViewAssert.assertAndReturnModelAttributeOfType(modelAndView, "SomeModelAttribute", String.class); ModelAndViewAssert.assertModelAttributeValue(modelAndView, "SomeModelAttribute", "Path_Var_Value"); ModelAndViewAssert.assertViewName(modelAndView, "viewName"); }
}
-
==============================
6.PathVariable 매핑을 요청 개체에 수동으로 삽입 할 수 있음을 발견했습니다. 이것은 분명히 이상적이지는 않지만 작동하는 것처럼 보입니다. 귀하의 예를 들면 다음과 같습니다 :
PathVariable 매핑을 요청 개체에 수동으로 삽입 할 수 있음을 발견했습니다. 이것은 분명히 이상적이지는 않지만 작동하는 것처럼 보입니다. 귀하의 예를 들면 다음과 같습니다 :
@Test public void test() { MockHttpServletRequest request = new MockHttpServletRequest(); request.setRequestURI("/test.html"); HashMap<String, String> pathvars = new HashMap<String, String>(); pathvars.put("id", "test"); request.setAttribute(HandlerMapping.URI_TEMPLATE_VARIABLES_ATTRIBUTE, pathvars); new AnnotationMethodHandlerAdapter().handle(request, new MockHttpServletResponse(), new MyController()); // assert something }
확실히 더 나은 옵션을 찾는 데 관심이 있습니다.
-
==============================
7.원래의 대답이 @PathVariable에 도움이 될지 잘 모르겠습니다. 방금 @PathVariable 테스트를 시도하고 다음 예외가 발생합니다.
원래의 대답이 @PathVariable에 도움이 될지 잘 모르겠습니다. 방금 @PathVariable 테스트를 시도하고 다음 예외가 발생합니다.
org.springframework.web.bind.annotation.support.HandlerMethodInvocationException : 핸들러 메소드를 호출하지 못했습니다 [public org.springframework.web.servlet.ModelAndView test.MyClass.myMethod (test.SomeType)]; 중첩 예외는 java.lang.IllegalStateException입니다 : @RequestMapping에서 @PathVariable [parameterName]을 찾을 수 없습니다.
그 이유는 요청의 경로 변수가 인터셉터에 의해 파싱되기 때문입니다. 다음 접근 방식은 나를 위해 작동합니다.
import static org.springframework.test.web.ModelAndViewAssert.*; @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration({"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; @Before public void setUp() throws Exception { this.request = new MockHttpServletRequest(); this.response = new MockHttpServletResponse(); this.handlerAdapter = applicationContext.getBean(HandlerAdapter.class); } ModelAndView handle(HttpServletRequest request, HttpServletResponse response) throws Exception { final HandlerMapping handlerMapping = applicationContext.getBean(HandlerMapping.class); final HandlerExecutionChain handler = handlerMapping.getHandler(request); assertNotNull("No handler found for request, check you request mapping", handler); final Object controller = handler.getHandler(); // if you want to override any injected attributes do it here final HandlerInterceptor[] interceptors = handlerMapping.getHandler(request).getInterceptors(); for (HandlerInterceptor interceptor : interceptors) { final boolean carryOn = interceptor.preHandle(request, response, controller); if (!carryOn) { return null; } } final ModelAndView mav = handlerAdapter.handle(request, response, controller); return mav; } @Test public void testDoSomething() throws Exception { request.setRequestURI("/test.html"); request.setMethod("GET"); final ModelAndView mav = handle(request, response); assertViewName(mav, "view"); // assert something else }
통합 테스트에 대한 새로운 블로그 게시물을 추가했습니다. mvc annotations
from https://stackoverflow.com/questions/1401128/how-to-unit-test-a-spring-mvc-controller-using-pathvariable by cc-by-sa and MIT license
'SPRING' 카테고리의 다른 글
[SPRING] @Value가있는 Spring Expression Language (SpEL) : 달러 대 해시 ($ vs. #) (0) | 2018.12.16 |
---|---|
[SPRING] 봄 범위의 프록시 빈 (0) | 2018.12.16 |
[SPRING] 다중 Spring @RequestMapping 주석 (0) | 2018.12.16 |
[SPRING] 인간을위한 JAAS (0) | 2018.12.16 |
[SPRING] 시로 대 스프링 시큐리티 [닫힌] (0) | 2018.12.16 |