복붙노트

[SPRING] JUnit 테스트에서 스프링 MVC가 밸리데이션을 호출하게하려면 어떻게해야합니까?

SPRING

JUnit 테스트에서 스프링 MVC가 밸리데이션을 호출하게하려면 어떻게해야합니까?

나는 Hibernate Validator 어노테이션으로 주석을 첨부 한 Browser라고 불리는 POJO를 가지고있다.

import org.hibernate.validator.constraints.NotEmpty;

public class Browser {

    @NotEmpty
    private String userAgent;
    @NotEmpty
    private String browserName;

...

}

컨트롤러 메서드가 유효성 검사 오류를 포착했는지 확인하려고하는 다음 단위 테스트를 작성했습니다.

@Test
public void testInvalidData() throws Exception {
    Browser browser = new Browser("opera", null);
    MockHttpServletRequest request = new MockHttpServletRequest();

    BindingResult errors = new DataBinder(browser).getBindingResult();
    // controller is initialized in @Before method
    controller.add(browser, errors, request);
    assertEquals(1, errors.getErrorCount());
}

다음은 내 컨트롤러의 add () 메소드입니다.

@RequestMapping(value = "/browser/create", method = RequestMethod.POST)
public String add(@Valid Browser browser, BindingResult result, HttpServletRequest request) throws Exception {
    if (result.hasErrors()) {
        request.setAttribute("errorMessage", result.getAllErrors());
        return VIEW_NAME;
    }

    browserManager.save(browser);

    request.getSession(false).setAttribute("successMessage",
            String.format("Browser %s added successfully.", browser.getUserAgent()));

    return "redirect:/" + VIEW_NAME;
}

내가 겪고있는 문제는 결과에 오류가 없으므로 @Valid가 인식되지 않는 것과 같습니다. 테스트 클래스에 다음을 추가하려고 시도했지만 문제가 해결되지 않았습니다.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration({"file:path-to/WEB-INF/spring-mvc-servlet.xml"})

누구든지 JUnit으로 테스트 할 때 @Valid를 인식 (및 유효성을 검사)하는 방법을 알고 있습니까?

감사,

매트

해결법

  1. ==============================

    1.유효성 검사는 컨트롤러 호출 전에 수행되므로 테스트에서이 유효성 검사를 호출하지 않습니다.

    유효성 검사는 컨트롤러 호출 전에 수행되므로 테스트에서이 유효성 검사를 호출하지 않습니다.

    컨트롤러를 직접 테스트하는 다른 방법이 있습니다. 대신 컨트롤러가 매핑 된 URL을 만들고 호출합니다. 다음은이를 수행하는 좋은 예입니다. http://rstoyanchev.github.com/spring-31-and-mvc-test/#1

    @RunWith(SpringJUnit4ClassRunner.class)
    @ContextConfiguration(loader=WebContextLoader.class, locations = {"classpath:/META-INF/spring/applicationContext.xml", "classpath:/META-INF/spring/applicationContext-test-override.xml", "file:src/main/webapp/WEB-INF/spring/webmvc-config.xml"})
    public class MyControllerTest {
    @Autowired
    WebApplicationContext wac;
    MockMvc mockMvc;
    
    @Before
    public void setup() {
        this.mockMvc = MockMvcBuilders.webApplicationContextSetup(this.wac).build();
    }
    
    @Test
    @Transactional
    public void testMyController() throws Exception {
        this.mockMvc.perform(get("/mycontroller/add?param=1").accept(MediaType.TEXT_HTML))
        .andExpect(status().isOk())
        .andExpect(model().attribute("date_format", "M/d/yy h:mm a"))
        .andExpect(model().attribute("myvalue", notNullValue()))
        .andExpect(model().attribute("myvalue", hasSize(2)))
        .andDo(print());
    }
    }
    

    POM (봄 마일스톤 레포 사용 필요) :

        <!-- required for spring-test-mvc -->
        <repository>
            <id>spring-maven-milestone</id>
            <name>Spring Maven Milestone Repository</name>
            <url>http://maven.springframework.org/milestone</url>
        </repository>
    ...
        <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-test-mvc</artifactId>
            <version>1.0.0.M1</version>
            <scope>test</scope>
        </dependency>
    

    참고 : spring-mvc-test lib는 제작 준비가 아직 완료되지 않았습니다. 구현에 약간의 차이가 있습니다. 나는 스프링 3.2를 위해 완전히 구현 될 계획이라고 생각한다.

    이 방법은 컨트롤러를 완전히 테스트 할 때 좋은 아이디어입니다. 컨트롤러 매핑을 엉망으로 만들기 쉽기 때문에 이것들은 실제로 단위 테스트를 받아야합니다.

  2. ==============================

    2.유효성 검사기는 메소드 매개 변수에 요청을 바인딩하는 프로세스 중 호출되는 컨트롤러 메소드보다 먼저 호출됩니다. 이 경우 컨트롤러 메서드를 직접 호출하므로 바인딩 및 유효성 검사 단계가 무시됩니다.

    유효성 검사기는 메소드 매개 변수에 요청을 바인딩하는 프로세스 중 호출되는 컨트롤러 메소드보다 먼저 호출됩니다. 이 경우 컨트롤러 메서드를 직접 호출하므로 바인딩 및 유효성 검사 단계가 무시됩니다.

    그것을 작동시키는 방법은 Spring MVC 스택을 통해 컨트롤러를 호출하는 것입니다. - 이것을 수행하는 몇 가지 방법이 있습니다. 가장 좋은 방법은 spring-test-mvc를 사용하여 좋은 메커니즘을 제공하는 것입니다. 스택을 통해 호출하십시오.

    스택을 통해 호출하는 또 다른 방법은 HandlerAdapter에 다음과 같이 테스트에 삽입하는 것입니다.

    @Autowired
    private RequestMappingHandlerAdapter handlerAdapter;
    

    그런 다음 테스트 :

    MockHttpServletRequest request = new MockHttpServletRequest("POST","/browser/create");
    MockHttpServletResponse response = new MockHttpServletResponse();
    httpRequest.addParameter(.... );//whatever is required to create Browser..
    ModelAndView modelAndView = handlerAdapter.handle(httpRequest, response, handler);
    
  3. ==============================

    3.기본적으로 this.controller = new MyController ()를 사용하여 POJO를 인스턴스화 한 다음 this.controller.add (...) 메서드를 호출했습니다. 컨텍스트가없는 단순한 객체를 가진 간단한 Java : @Valid는 고려되지 않습니다.

    기본적으로 this.controller = new MyController ()를 사용하여 POJO를 인스턴스화 한 다음 this.controller.add (...) 메서드를 호출했습니다. 컨텍스트가없는 단순한 객체를 가진 간단한 Java : @Valid는 고려되지 않습니다.

    @ContextConfiguration은 가능한 사용자 정의 유효성 검사기 등으로 가능한 빈을로드하지만, @Valid를 처리하는 마법을 수행하지는 않습니다.

    필요한 것은 컨트롤러의 add 메소드에 대한 요청을 에뮬레이션하는 것이다. 유효성 검사를 포함하여 완전히 에뮬레이션합니다. Spring 테스트 기능 (MockHttpServletRequest를 인스턴스화하기 위해)을 사용했기 때문에 그리 멀지 않았습니다.

    Spring 3.0.x 또는 그 이하 버전을 사용한다면,

    new AnnotationMethodHandlerAdapter()
          .handle(request, new MockHttpServletResponse(), this.controller);
    

    그것을 작동하게합니다.

    Spring 3.1 이상을 사용하면 위의 해결책이 작동하지 않습니다 (자세한 정보는이 링크 참조)! 스프링 (Spring) 팀의이 라이브러리를 사용하면 다음 봄 버전에서이 라이브러리를 통합 할 때까지 기다리는 동안 소리가 나지 않아도됩니다. 그렇다면 당신은 뭔가를해야 할 것입니다.

    myMockController = MockMvcBuilders.standaloneSetup(new MyController()).build();
    myMockController.perform(get("/browser/create")).andExpect(...);
    

    또한 Rossen Stoyanchev의 흥미로운 슬라이드를 살펴보십시오 (여기에서 우리가 말하는 부분은 슬라이드 # 116에서 시작됩니다).

    참고 : 이러한 유형의 테스트가 단위 테스트 또는 통합 테스트로 간주되는지 여부에 대한 논쟁에 참여하지 않을 것입니다. 어떤 사람들은 요청의 전체 경로를 모방하기 때문에 여기에서 수행하는 통합 테스트라고 말합니다. 그러나 다른 한편으로는 Mockito의 @Mock 주석을 사용하여 컨트롤러를 조롱 할 수 있습니다 (또는 다른 조롱 프레임 워크와 비슷한 기능을 수행 할 수 있습니다). 그래서 일부 테스트에서는 테스트 범위를 거의 "단위 테스트"로 줄일 수 있다고 말합니다 . 물론 이전의 Java + 조롱 프레임 워크를 사용하여 컨트롤러를 테스트 할 수도 있지만이 경우에는 @Valid 유효성 검사를 테스트 할 수 없습니다. 당신의 선택을해라! :)

  4. from https://stackoverflow.com/questions/12308213/how-do-i-get-spring-mvc-to-invoke-validation-in-a-junit-test by cc-by-sa and MIT license