Spring autowire HttpServletRequest в интеграционных тестах

У нас есть одноэлементные контроллеры, такие как

@Controller
class C {
  @Autowire MyObject obj;
  public void doGet() {
    // do something with obj
  }
}

MyObject создается в фильтре/перехватчике и помещается в атрибуты HttpServletRequest. Затем он получается в @Configuration:

@Configuration
class Config {
  @Autowire
  @Bean @Scope("request")
  MyObject provideMyObject(HttpServletRequest req) {
      return req.getAttribute("myObj");
  }
}

Все работает хорошо в основном коде, но не в тестировании: когда я запускаю его из интеграционного теста:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("/web-application-config_test.xml")
class MyTest {
    @Autowired
    C controller;

    @Test
    void test() {
       // Here I can easily create "new MockHttpServletRequest()"
       // and set MyObject to it, but how to make Spring know about it?
       c.doGet();
    }
}

он жалуется, что NoSuchBeanDefinitionException: No matching bean of type [javax.servlet.http.HttpServletRequest]. (Сначала он жаловался на то, что область запроса не активна, но я разрешил ее с помощью CustomScopeConfigurer с SimpleThreadScope, как было предложено здесь).

Как сообщить Spring инъекции о моем MockHttpServletRequest? Или напрямую MyObject?


person Dzmitry Lazerka    schedule 18.06.2013    source источник


Ответы (1)


Обойти временно, но похоже правильный подход: в Config вместо req.getAttribute("myObj") написать

RequestAttributes requestAttributes = RequestContextHolder.currentRequestAttributes();
return (MyObject) requestAttributes.getAttribute("myObj", RequestAttributes.SCOPE_REQUEST);

поэтому ему больше не нужен экземпляр HttpServletRequest. И заполните его в тесте:

MockHttpServletRequest request = new MockHttpServletRequest();
request.setAttribute("myObj", /* set up MyObject instance */)
RequestContextHolder.setRequestAttributes(new ServletWebRequest(request));
person Dzmitry Lazerka    schedule 15.07.2013