【发布时间】:2019-10-01 20:51:17
【问题描述】:
查看this post,其中 @slim 给出了一个接近我所要求的解决方案。我正在尝试在下面的课程中编写单元测试。我正在拉出 sessionId。 (在 doFilterInternal 方法中查找 String sessId)
@Component
public class AppLoggingFilter extends OncePerRequestFilter {
private AppLoggingMDCService mdcService;
@Inject
public AppLoggingFilter(AppLoggingMDCService appLoggingMDCService) {
Assert.notNull(appLoggingMDCService, "AppLoggingMDCService must not be null");
this.mdcService = appLoggingMDCService;
}
@Override
protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException {
Principal principal = request.getUserPrincipal();
String sessId = DigestUtils.sha256Hex(request.getSession().getId());
if (principal != null) {
String userId = principal.getName();
mdcService.put(AppLoggingMDCService.LOG_KEY_USER_ID, userId);
}
mdcService.put(AppLoggingMDCService.LOG_KEY_SESSION_ID, sessId);
try {
filterChain.doFilter(request, response);
} finally {
mdcService.removeAll();
}
}
下面的测试自然会失败,因为我没有有效的会话。显然,每当我调用 filter.doFilterInternal(request, response, filterChain); 时,我都会遇到空指针异常。在测试类中,“模拟会话”没有设置,也没有 ID。在我的单元测试中,我有这个。
@RunWith(SpringJUnit4ClassRunner.class)
@ActiveProfiles(value = {"test"})
public class AppLoggingFilterUnitTest {
@Mock
AppLoggingMDCService mdcService;
@Mock
MockHttpServletRequest request;
@Mock
MockHttpServletResponse response;
@Mock
MockFilterChain filterChain;
@Mock
MockHttpSession session;
@InjectMocks
AppLoggingFilter filter;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
request.setSession(session);
}
@Test
public void testCustomerIdHasBeenLogged() throws Exception {
String customerId = "1234";
when(request.getHeader(AuthorizationConstants.CUSTOMER_KEY)).thenReturn(customerId);
filter.doFilterInternal(request, response, filterChain);
verify(mdcService, times(1)).put(AppLoggingMDCService.LOG_KEY_CUST_ID,customerId);
}
}
所以回到我的问题,如何模拟为有效的模拟“MockHttpSession”,这样我的其他测试就不会失败?
更新
所以我像这样将会话添加到我的测试类中。在我的设置方法中,我说要返回“模拟”会话。只有当我打电话时测试才通过
String sessId = request.getSession().getId();。如果我尝试做 DigestUtils.sha256Hex 之类的
String sessId = DigestUtils.sha256Hex(request.getSession().getId());,所有测试都因空指针而失败。我不确定为什么。模拟 DigestUtils 没有多大意义。
@Mock
AppLoggingMDCService mdcService;
@Mock
HttpServletRequest request;
@Mock
HttpServletResponse response;
@Mock
FilterChain filterChain;
@Mock
HttpSession session;
@InjectMocks
AppLoggingFilter filter;
@Before
public void setUp() {
MockitoAnnotations.initMocks(this);
when(request.getSession()).thenReturn(this.session);
}
【问题讨论】:
-
在你有
request.getSession()的代码中你没有嘲笑这个。这就是问题所在。而不是对请求对象执行 setsession,而是模拟 getsession 调用 -
你的测试太复杂了。
MockHttpSession旨在由您自己实例化,而不是被 mockito 模拟(适用于所有Mock*相关类)。 -
@pvpkiran 我使用了您的建议并模拟了会话,如我上面的更新中所示。但是,由于空指针,我仍然遇到更新中描述的测试失败。我不确定我错过了什么。
标签: spring junit spring-security mockito