2010-02-22 29 views
9

Bir @Valid ek açıklamasının bir denetleyici sınıfından yanlışlıkla kaldırıldığı geçen gün bir sorunla karşılaştım. Maalesef testlerimizden hiçbirini kırmadı. Ünite testlerimizden hiçbiri aslında Spring AnnotationMethodHandlerAdapter yolunu kullanmaz. Kontrolör sınıflarımızı doğrudan test ediyoruz.Spring @MVC ek açıklamalarını sınama

@MVC ek açıklamalarım yanlışsa, nasıl başarısız olacak bir birim veya entegrasyon testi nasıl yazabilirim? Bir MockHttpServlet ya da bir şey ile ilgili denetleyici bulmak ve uygulamak için Bahar sorabilirsiniz bir yolu var mı?

+1

, olur mu? Benim için bir entegrasyon testi endişesi gibi görünüyor. –

cevap

1

benim blog yazısı bakın g 3.2 (SNAPSHOT kullanılabilir) veya spring-test-mvc (https://github.com/SpringSource/spring-test-mvc) ile şu şekilde yapabilirsiniz:

İlk önce biz istemedikçe Doğrulama'yı taklit ederiz Doğrulayıcıyı test etmek için, sadece doğrulama çağrılıp yapılmadığını bilmek istiyorum.

public class LocalValidatorFactoryBeanMock extends LocalValidatorFactoryBean 
{ 
    private boolean fakeErrors; 

    public void fakeErrors () 
    { 
     this.fakeErrors = true; 
    } 

    @Override 
    public boolean supports (Class<?> clazz) 
    { 
     return true; 
    } 

    @Override 
    public void validate (Object target, Errors errors, Object... validationHints) 
    { 
     if (fakeErrors) 
     { 
      errors.reject("error"); 
     } 
    } 
} 

bu test sınıftır: Sen ünite bir şerh sınamak olmaz

@RunWith(SpringJUnit4ClassRunner.class) 
@WebAppConfiguration 
@ContextConfiguration 
public class RegisterControllerTest 
{ 
@Autowired 
private WebApplicationContext wac; 
private MockMvc mockMvc; 

    @Autowired 
    @InjectMocks 
    private RegisterController registerController; 

    @Autowired 
    private LocalValidatorFactoryBeanMock validator; 

    @Before 
    public void setup () 
    { 
    this.mockMvc = MockMvcBuilders.webAppContextSetup(this.wac).build(); 
    // if you want to inject mocks into your controller 
      MockitoAnnotations.initMocks(this); 
    } 

    @Test 
    public void testPostValidationError () throws Exception 
    { 
     validator.fakeErrors(); 
     MockHttpServletRequestBuilder post = post("/info/register"); 
     post.param("name", "Bob"); 
     ResultActions result = getMockMvc().perform(post); 
      // no redirect as we have errors 
     result.andExpect(view().name("info/register")); 
    } 

    @Configuration 
    @Import(DispatcherServletConfig.class) 
    static class Config extends WebMvcConfigurerAdapter 
    { 
     @Override 
     public Validator getValidator () 
     { 
      return new LocalValidatorFactoryBeanMock(); 
     } 

     @Bean 
     RegisterController registerController () 
     { 
      return new RegisterController(); 
     } 
    } 
} 
3

Elbette. Testinizin kendi DispatcherServlet'u neden başlatabileceğinin bir nedeni yoktur, içerik tanımlama dosyasının yeri de dahil olmak üzere bir kapta (örneğin, ServletContext) alacağı çeşitli öğelerle enjekte edin.

Yay MockServletContext, MockHttpServletRequest ve MockHttpServletResponse da dahil olmak üzere, bu amaçla sunucu uygulaması ile ilgili MockXYZ sınıfları, çeşitli gelir. Onlar her zamanki anlamda nesneleri "sahte" değiller, daha çok aptal taslaklar gibi, ama işi yapıyorlar.

Sunucunun sınama bağlamında olağan MVC ile ilgili fasulyelerin yanı sıra fasulyelerinizin sınanması gerekir. Servlet başlatıldıktan sonra, sahte istekleri ve yanıtları oluşturun ve bunları serverin service() yöntemine gönderin. İstek doğru bir şekilde yönlendirilirse, sonuçları sahte yanıta yazılan şekilde kontrol edebilirsiniz.

13

Bu tür bir şey için bütünleştirme testleri yazarım. Eğer bir doğrulama Ek açıklamalar içeren fasulye var ki:

public class MyForm { 
    @NotNull 
    private Long myNumber; 

    ... 
} 

ve Gönderme

@Controller 
@RequestMapping("/simple-form") 
public class MyController { 
    private final static String FORM_VIEW = null; 

    @RequestMapping(method = RequestMethod.POST) 
    public String processFormSubmission(@Valid MyForm myForm, 
      BindingResult result) { 
     if (result.hasErrors()) { 
      return FORM_VIEW; 
     } 
     // process the form 
     return "success-view"; 
    } 
} 

işleyen bir kontrolör ve @Valid ve @NotNull açıklamalar doğru kablolu olduğunu test etmek istiyorum:

@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 testProcessFormSubmission() throws Exception { 
     request.setMethod("POST"); 
     request.setRequestURI("/simple-form"); 
     request.setParameter("myNumber", ""); 

     final ModelAndView mav = handle(request, response); 
     // test we're returned back to the form 
     assertViewName(mav, "simple-form"); 
     // make assertions on the errors 
     final BindingResult errors = assertAndReturnModelAttributeOfType(mav, 
       "org.springframework.validation.BindingResult.myForm", 
       BindingResult.class); 
     assertEquals(1, errors.getErrorCount()); 
     assertEquals("", errors.getFieldValue("myNumber"));   
    } 

yaklaşan Sprin olarak integration testing Spring's MVC annotations

+0

Bu friggin 'harika. Bu tam olarak aradığım şey gibiydi! Teşekkürler! –

İlgili konular