Spring autowire HttpServletRequest in integration

2019-08-06 19:57发布

We have singleton controllers like

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

MyObject is created in a filter/interceptor and is put into HttpServletRequest attributes. Then it's obtained in @Configuration:

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

Everything works well in main code, but not in testing: when I run it from an integration test:

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

it complains that NoSuchBeanDefinitionException: No matching bean of type [javax.servlet.http.HttpServletRequest]. (At first, it complained about request scope is not active, but I resolved it using CustomScopeConfigurer with SimpleThreadScope as suggested here).

How to let Spring injection know about my MockHttpServletRequest? Or directly MyObject?

1条回答
我命由我不由天
2楼-- · 2019-08-06 20:16

Workarounded temporarily, but it looks like the right approach: in Config, instead of req.getAttribute("myObj"), write

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

so it does not need a HttpServletRequest instance anymore. And fill it in test:

MockHttpServletRequest request = new MockHttpServletRequest();
request.setAttribute("myObj", /* set up MyObject instance */)
RequestContextHolder.setRequestAttributes(new ServletWebRequest(request));
查看更多
登录 后发表回答