2012-09-06 34 views
11

Tôi có một POJO được gọi là Trình duyệt mà tôi đã chú thích với chú thích Hibernate Validator.Làm cách nào để có được Spring MVC gọi xác thực trong một bài kiểm tra JUnit?

import org.hibernate.validator.constraints.NotEmpty; 

public class Browser { 

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

... 

} 

Tôi đã viết kiểm tra đơn vị sau đây cố gắng xác minh phương thức Bộ điều khiển của tôi phát hiện lỗi xác thực.

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

Dưới đây là bộ điều khiển của tôi add() phương pháp:

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

Vấn đề tôi đang gặp là kết quả mà không bao giờ có lỗi, vì vậy nó giống như @Valid là không nhận được công nhận. Tôi đã thử thêm sau đây vào lớp thử nghiệm của tôi, nhưng nó không giải quyết được vấn đề.

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

Có ai biết làm thế nào để @Valid được công nhận (và được xác thực) khi thử nghiệm với JUnit không?

Cảm ơn,

Matt

Trả lời

3

Việc xác nhận được thực hiện trước khi cuộc gọi đến bộ điều khiển, vì vậy thử nghiệm của bạn không được gọi xác nhận này.

Có một cách tiếp cận khác để kiểm tra bộ điều khiển, nơi bạn không gọi trực tiếp bộ điều khiển. Thay vào đó bạn xây dựng và gọi URL mà bộ điều khiển được ánh xạ. Dưới đây là một ví dụ tốt về làm thế nào để làm điều này: 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 (cần phải sử dụng lò xo mốc repo):

<!-- 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> 

LƯU Ý: các lib mùa xuân-MVC-test không phải là sản xuất sẵn sàng chưa. Có một số khoảng trống trong việc thực hiện. Tôi nghĩ rằng kế hoạch của nó sẽ được thực hiện đầy đủ cho mùa xuân 3.2.

Cách tiếp cận này là một ý tưởng tuyệt vời vì nó kiểm tra đầy đủ bộ điều khiển của bạn. Thật dễ dàng để làm hỏng các ánh xạ điều khiển của bạn, vì vậy chúng thực sự cần phải được kiểm tra đơn vị.

2

Trình xác thực được gọi trước các phương thức điều khiển được gọi - trong quá trình ràng buộc yêu cầu đối với các tham số phương thức. Vì trong trường hợp này, bạn đang gọi trực tiếp phương thức điều khiển, các bước ràng buộc và xác thực đang bị bỏ qua.

Cách để thiết bị hoạt động sẽ thực hiện cuộc gọi đến bộ điều khiển thông qua ngăn xếp Spring MVC - Có một số cách để thực hiện việc này, tôi cảm thấy cách tốt nhất là sử dụng spring-test-mvc. gọi qua ngăn xếp.

Một cách khác để gọi thông qua ngăn xếp là để tiêm trong HandlerAdapter để thử nghiệm theo cách này:

@Autowired 
private RequestMappingHandlerAdapter handlerAdapter; 

Sau đó, trong bài kiểm tra:

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

Về cơ bản bạn khởi tạo một POJO với this.controller = new MyController(), sau đó được gọi là phương pháp this.controller.add(...). Chỉ đơn giản Java với một đối tượng đơn giản, không có bất kỳ ngữ cảnh nào: @Valid không được tính đến.

@ContextConfiguration sẽ chỉ tải đậu có thể của bạn, với trình xác thực tùy chỉnh có thể có và như vậy, nhưng nó sẽ không làm phép thuật xử lý @Valid.

Những gì bạn cần là một cái gì đó để mô phỏng yêu cầu đối với phương thức add của bộ điều khiển. Hoàn toàn mô phỏng nó, xác nhận bao gồm. Bạn đã không làm như vậy, vì bạn đã sử dụng một số cơ sở thử nghiệm Spring (để khởi tạo một MockHttpServletRequest).

Nếu bạn sử dụng 3.0.x mùa xuân hoặc ít, bạn cần làm

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

để làm cho nó làm việc.

Nếu bạn sử dụng Spring 3.1+, giải pháp trên sẽ không hoạt động (see this link for more info)! Bạn sẽ cần phải sử dụng this library (từ nhóm Spring, do đó, âm thanh của nó không lo lắng), trong khi chờ đợi cho họ để tích hợp nó trong phiên bản Spring tiếp theo. Sau đó, bạn sẽ phải làm một cái gì đó giống như

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

Cũng có một cái nhìn tại những rất interesting slides từ Rossen Stoyanchev (phần chúng ta đang nói về ở đây bắt đầu từ trượt # 116)!

Lưu ý: Tôi sẽ không tham gia vào cuộc tranh luận về việc loại thử nghiệm này có được coi là thử nghiệm đơn vị hay thử nghiệm tích hợp hay không. Một số người sẽ nói đây là thử nghiệm tích hợp thay vì chúng tôi đang làm ở đây, vì chúng tôi mô phỏng đường dẫn đầy đủ của một yêu cầu. Nhưng mặt khác, bạn vẫn có thể giả lập bộ điều khiển của mình bằng các chú thích @Mock từ Mockito (hoặc thực hiện các công cụ tương tự với bất kỳ khung mocking khác), vì vậy một số người khác sẽ nói rằng bạn có thể giảm phạm vi của bài kiểm tra gần như "kiểm tra đơn vị" thuần túy . Tất nhiên bạn có thể lựa chọn và hoàn toàn đơn vị kiểm tra bộ điều khiển của bạn với Java cũ đơn giản + một khuôn khổ mocking, nhưng trong trường hợp này điều này sẽ không cho phép bạn kiểm tra xác nhận @Valid. Hãy lựa chọn! :)

Các vấn đề liên quan