我正在使用单元测试中的@WebMvcTest
对控制器进行单元测试。我的控制器从RequestAttributes
检索了RequestContextHolder
数据:
RequestContextHolder.currentRequestAttributes().getAttribute(name, RequestAttributes.SCOPE_REQUEST)
此处存储的数据在拦截器中设置:
RequestAttributes reqAttr = RequestContextHolder.currentRequestAttributes();
reqAttr.setAttribute(name, value, RequestAttributes.SCOPE_REQUEST);
RequestContextHolder.setRequestAttributes(reqAttr, true);
在我的控制器单元测试中,拦截器未运行,因此我尝试在运行测试之前设置请求属性,但出现此错误:
java.lang.IllegalStateException:未找到线程绑定请求:您是在实际Web请求之外引用请求属性,还是在原始接收线程之外处理请求?如果您实际上是在Web请求中操作并且仍然收到此消息,则您的代码可能正在DispatcherServlet外部运行:在这种情况下,请使用RequestContextListener或RequestContextFilter公开当前请求。
我已经尝试过此答案https://stackoverflow.com/a/9419859/5545327。我加了:
@Mock
private RequestAttributes attrs;
@Before
public void before() {
MockitoAnnotations.initMocks(this);
RequestContextHolder.setRequestAttributes(attrs);
}
@Test
public void testController() {
when(requestAttributes.getAttribute(eq("<attribute name>"),
eq(RequestAttributes.SCOPE_REQUEST))).thenReturn(<mockReturn>);
// do your test...
}
但是它不起作用。错误消失了,但是控制器正在从null
获取RequestContextHolder
的值。顺便说一下,我正在通过以下方式测试我的控制器:
mockMvc.perform(post("<url>").content("<post params here>")).andExpect(status().isOk());
mockMvc
来自@WebMvcTest
。
注意:我有一个用于集成测试的类,这就是为什么我在这里使用@WebMvcTest
而不是@SpringBootTest
由于我对Spring还很陌生,所以我希望您能提供一个描述性的答案。
谢谢!
编辑:
RequestContextHolder
中的请求属性。另外,我需要的数据不是来自HttpRequest,而是基于HttpRequest。我嘲笑它,因为我知道实际的请求,因为这是我的单元测试。代码如下:
@RunWith(SpringRunner.class)
@WebMvcTest
@OverrideAutoConfiguration(enabled = true)
@ActiveProfiles("test")
public abstract class BaseControllerTest {
@Autowired
protected MockMvc mockMvc;
}
public class ControllerTest extends BaseControllerTest {
@Test
public void testControllerMethod() {
mockMvc.perform(post("<url>").content("<post params here>")).andExpect(status().isOk());
// some more codes here
}
}
public class Controller {
@PostMapping
public String controllerMethod() {
// some more codes here
Object myObject = RequestContextHolder.currentRequestAttributes().getAttribute(name, RequestAttributes.SCOPE_REQUEST);
// some more codes here
}
}