【问题标题】:How to Mock with MockHttpSession and Junit如何使用 MockHttpSession 和 Junit 进行模拟
【发布时间】: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


【解决方案1】:

您在测试中做了很多事情,这太复杂了。移除跑步者,移除 Mock* 的 Mockito,因为它们需要实例化而不是模拟。


public class AppLoggingFilterUnitTest {

    @Mock
    private AppLoggingMDCService mdcService;

    @InjectMocks
    private AppLoggingFilter filter;

    private MockHttpServletRequest request;
    private MockHttpServletResponse response = new MockHttpServletResponse();
    private MockFilterChain filterChain = new MockFilterChain();


    @Before
    public void setUp() {
        MockitoAnnotations.initMocks(this);
        this.request = new MockHttpServletRequest();
        this.request.addHeader(AuthorizationConstants.CUSTOMER_KEY, "1234"); 
    }

    @Test
    public void testCustomerIdHasBeenLogged() throws Exception {
        filter.doFilterInternal(request, response, filterChain);
        verify(mdcService, times(1)).put(AppLoggingMDCService.LOG_KEY_CUST_ID,customerId);
    }
}

通过为Mock* 类创建模拟,您基本上破坏了这些类的目的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-31
    • 2021-03-02
    • 2011-09-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多