我添加了一个拦截器,它在会话中查找loggedInUser并重定向到登录页面并显示错误消息,指示用户登录以继续。我正在使用flash属性传递此消息。当我运行应用程序时,整个设置工作正常。
但是我无法使用MockMvc声明flash属性。
public class LoginInterceptor extends HandlerInterceptorAdapter{
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception {
String loginUrl = request.getContextPath() + "/login";
if(request.getSession().getAttribute("loggedInUser") == null) {
FlashMap flashMap = new FlashMap();
flashMap.put("loginError", "Please login to continue");
FlashMapManager flashMapManager = RequestContextUtils.getFlashMapManager(request);
flashMapManager.saveOutputFlashMap(flashMap, request, response);
response.sendRedirect(loginUrl);
return false;
}
return true;
}
}
在测试用例中,我可以断言当我没有登录时调用“/ user”,它会被重定向到“/ login”页面。但是我无法断言flash属性。
@WebMvcTest(UserProfileController.class)
@RunWith(SpringRunner.class)
public class UserProfileControllerTest {
@Autowired
private MockMvc mockMvc;
@Test
public void testForNotLoggedInCall() throws Exception{
MvcResult mvcResult = mockMvc.perform(get("/user")).andDo(print())
.andExpect(status().is3xxRedirection())
.andExpect(flash().attribute("loginError", equalTo("Please login to continue")))
.andExpect(redirectedUrl("/login"))
.andReturn();
assertNotNull(mvcResult);
List<HandlerInterceptor> interceptors = Arrays.asList(mvcResult
.getInterceptors());
assertTrue(
"Expecting login interceptor in this path for cases where there is no logged in user",
interceptors.stream().anyMatch(
i -> i.getClass().equals(LoginInterceptor.class)));
FlashMap flashMap = mvcResult.getFlashMap();
assertNotNull(flashMap);
assertEquals("Please login to continue", flashMap.get("loginError"));
}
}
我使用过这两种方法: 1)
andExpect(flash().attribute("loginError", equalTo("Please login to continue")))
2)还可以从mvcResult获取flashMap:
FlashMap flashMap = mvcResult.getFlashMap();
没有任何作用。
并且下面的print()结果显示: flash映射具有预期的属性,但MockHttpServletRequest中的flashAttribute为null
有人可以解释我做错了什么吗?以及如何断言flash属性?
2017-10-02 14:09:12.470 DEBUG 5836 --- [主要] s.w.s.m.m.a.RequestMappingHandlerMapping:查找处理程序方法 for path / user 2017-10-02 14:09:12.502 TRACE 5836 --- [
main] s.w.s.m.m.a.RequestMappingHandlerMapping:找到1个匹配项 [/ user]的映射:[{[/ user],methods = [GET]}] 2017-10-02 14:09:12.517 DEBUG 5836 --- [主要] s.w.s.m.m.a.RequestMappingHandlerMapping:返回处理程序方法 [public org.springframework.web.servlet.ModelAndView com.foo.library.controller.UserProfileController.showUserProfilePage(的javax.servlet.http.HttpSession)] 2017-10-02 14:09:12.517 DEBUG 5836 --- [主要] o.s.b.f.s.DefaultListableBeanFactory:返回缓存的实例 singleton bean的用户'userProfileController'2017-10-02 14:09:12.533 TRACE 5836 --- [主要] o.s.t.web.servlet.TestDispatcherServlet:测试处理程序适配器 [org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter@253c1256] 2017-10-02 14:09:12.533 DEBUG 5836 --- [主要] o.s.t.web.servlet.TestDispatcherServlet:Last-Modified值 [/ user]是: - 1 2017-10-02 14:09:12.533 DEBUG 5836 --- [main] o.s.w.s.support.SessionFlashMapManager:保存FlashMap = FlashMap [attributes = {loginError =请登录以继续}, targetRequestPath = null,targetRequestParams = {}] 2017-10-02 14:09:12.533 TRACE 5836 --- [主要] o.s.t.web.servlet.TestDispatcherServlet:清除线程绑定 请求上下文: org.springframework.mock.web.MockHttpServletRequest@304a3655 2017-10-02 14:09:12.533 DEBUG 5836 --- [主要] o.s.t.web.servlet.TestDispatcherServlet:已成功完成 要求2017-10-02 14:09:12.533 TRACE 5836 --- [主要] o.s.w.c.s.GenericWebApplicationContext:发布事件 org.springframework.web.context.support.GenericWebApplicationContext@2fb3536e: ServletRequestHandledEvent:url = [/ user];客户= [127.0.0.1]。 方法= [GET];的servlet = [];会话= 1;用户= [零]。时间= [78ms]; status = [确定] 2017-10-02 14:09:12.533 DEBUG 5836 --- [主要] o.s.b.w.f.OrderedRequestContextFilter:清除线程绑定 请求上下文: org.springframework.mock.web.MockHttpServletRequest@304a3655MockHttpServletRequest: HTTP方法= GET 请求URI = / user 参数= {} 标题= {}
处理程序: Type = com.foo.library.controller.UserProfileController Method = public org.springframework.web.servlet.ModelAndView com.foo.library.controller.UserProfileController.showUserProfilePage(的javax.servlet.http.HttpSession)
异步: 异步启动= false 异步结果= null
已解决的异常: Type = null
的ModelAndView: 查看名称= null View = null Model = null
FlashMap: Attributes = null
MockHttpServletResponse: 状态= 302 错误消息= null 标题= {Location = [/ login]} 内容类型= null 身体= 转发的URL = null重定向的URL = / login Cookies = []
修改
在进一步调试时,我发现FlashAttributeResultMatcher正在调查outputFlashMap以进行断言,我在拦截器中使用了FlashMapManager,该拦截器在会话中使用了另一个属性。
有人可以解释inputFlashMap, outputFlashMap and FlashMapManager之间的区别吗?我们使用它们的理想场景是什么?