Вопрос

На днях я столкнулся с проблемой, когда аннотация @Valid была случайно удалена из класса контроллера. К сожалению, это не сломало ни одного из наших тестов. Ни один из наших модульных тестов фактически не проявляет весны AnnotationMethodHandlerAdapter путь. Мы просто тестируем наши классы контроллера напрямую.

Как я могу написать блок или интеграционный тест, который правильно пройдет, если мои аннотации @MVC неверны? Есть ли способ, которым я могу попросить Spring найти и использовать соответствующий контроллер с помощью Mockhttpservlet или чего -то еще?

Это было полезно?

Решение

В предстоящей весне 3.2 (снимки доступны) или с Spring-test-mvc (https://github.com/springsource/spring-test-mvc) вы можете сделать это так:

Сначала мы подражаем проверке, поскольку мы не хотим проверять валидатор, просто хотим знать, вызвана ли проверка.

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

Это наш тестовый класс:

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

Другие советы

Я пишу интеграционные тесты для такого рода вещей. Скажем, у вас есть боб с аннотациями проверки:

public class MyForm {
    @NotNull
    private Long myNumber;

    ...
}

и контроллер, который обрабатывает представление

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

И вы хотите проверить, что аннотации @Valid и @notnull правильно подключены:

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

Смотрите мой пост в блоге на Интеграционные тестирование Annotations MVC Spring

Конечно. Нет причин, по которым ваш тест не может создать его собственный DispatcherServlet, введите его с различными элементами, которые он будет иметь в контейнере (например, ServletContext), включая местоположение файла определения контекста.

Весна поставляется с разнообразными сервлетами MockXYZ занятия для этой цели, включая MockServletContext, MockHttpServletRequest а также MockHttpServletResponse. Анкет Они на самом деле не «высмеивают» объекты в обычном смысле, они больше похожи на тупых заглушек, но делают работу.

В контексте испытания сервлета будут обычные бобы, связанные с MVC, плюс ваши бобы для проверки. После того, как сервлет будет инициализирован, создайте фиктивные запросы и ответы и подайте их в сервис service() метод Если запрос будет направлен правильно, вы можете проверить результаты, написанные на макете.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top