新闻对象的新闻测试方法和使用静态方法

时间:2017-01-10 16:17:47

标签: java spring unit-testing

我有一个非常简单的方法,使用Spring框架,除了与注入服务交互外,还必须 new 一个对象,然后使用静态方法获取另一个对象,如下所示:

// These two guys are injected:
UserDetailsService userDetailsService;
AuthenticationManager authManager;

UserDetails userDetails = userDetailsService.loadUserByUsername(name);

Authentication token = new UsernamePasswordAuthenticationToken(userDetails,
        password, userDetails.getAuthorities());

Authentication authentication = authenticationManager.authenticate(token);

SecurityContextHolder.getContext().setAuthentication(authentication);

我应该如何测试它(确保调用方法并将正确的参数传递给它们)?我不能简单地模仿 UsernamePasswordAuthenticationToken SecurityContextHolder 。我可以为这两件事创建工厂,这样可以解决问题,但对于像这样简单的事情来说,感觉就像是一种巨大的过度杀伤力。再加上我必须测试工厂。还有其他方法吗?

2 个答案:

答案 0 :(得分:1)

@KlausGroenbaek的答案描述了使用JUnit Framework完成的模块测试验收测试。这是一种重要的测试类型,绝对是您想要做的事情。

但它不是单元测试

UnitTests单独测试您的代码的一小部分的行为,这意味着您的单元与之通信的任何内容都应该是模拟或数据传输对象(DTO)(或者“太简单而不能失败”)。

Wen我尝试将此问题应用到您的代码中,您应该重新调出静态方法调用SecurityContextHolder.getContext(),并通过包private获取结果( context ?) / em> getter或将它注入你的课程。

然后,您可以使用Mockito或任何其他模拟框架模拟三个依赖项contextuserDetailsServiceauthManager。如果包私有 getter使用Mockito.spy()Mockito.doReturn(cotextMock).when(myClass.getContext())(或相当于您选择的模拟框架)。
当使用Mockito时,我更喜欢使用 spy 对象的这个表单,因为它执行模拟方法,因为更常见的when().thenReturn()表单。

可以通过捕获方法调用UsernamePasswordAuthenticationToken的参数来间接检查authenticationManager.authenticate(token)的实例化。 Mockito为此提供了ArgumentCaptor util类。

答案 1 :(得分:0)

我有两个答案,之前我已经完成了两个答案。

您现在使用的方法是在没有Spring安全过滤器链的情况下在控制器/服务级别进行测试。如您所知,这意味着您必须自己管理ThreadLocal SecurityContext。 通常,当您想在JUnit测试之前执行某些操作时,请将其放在@Before带注释的方法中。

@Before
public void before() {
    UserDetails userDetails = userDetailsService.loadUserByUsername(name);

    Authentication token = new UsernamePasswordAuthenticationToken(userDetails,
            password, userDetails.getAuthorities());

    Authentication authentication = authenticationManager.authenticate(token);

    SecurityContextHolder.getContext().setAuthentication(authentication);
}

清理我们使用@After

@After
public void test() {
    SecurityContextHolder.getContext().setAuthentication(null);
}

这种方法有效,但它有两个主要缺点。它没有检查Spring过滤器链,也没有检查Controller请求路由 - 所以我已经停止编写看起来像这样的测试,因为我找到了一种更好的方法来测试完整的Web堆栈而不使用Web服务器。

欢迎你的新朋友MockMvc!它允许您配置测试整个Web层的Spring Test。这允许您检查用户是否被重定向回登录,但在凭据错误时会例外。并验证发送无效的JSON将导致正确的400 Bad输入。

我建议您先阅读MockMvc文档。熟悉基础知识后,您可以按照here所述的方式应用SpringSecurity的SecurityMockMvcConfigurers.springSecurity()