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

// 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。我可以为这两种情况创建工厂,这将解决问题,但是对于像这样简单的事情来说,这感觉像是一个巨大的过大杀伤力。另外,我还必须测试工厂。还有其他方法吗?

最佳答案

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

但这不是单元测试。

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



我试图在您的代码中使用它,您应该重新调用静态方法SecurityContextHolder.getContext()并通过包私有getter获取结果(上下文?)或将其注入您的类中。

然后,您可以使用Mockito或任何其他模拟框架来模拟三个依赖项contextuserDetailsServiceauthManager。如果是包私有getter,则将Mockito.spy()Mockito.doReturn(cotextMock).when(myClass.getContext())一起使用(或与您选择的模拟框架等效)。
使用Mockito时,我更喜欢带有间谍对象的这种形式,因为它不像更常见的when().thenReturn()形式那样执行模拟方法。

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

10-07 19:52
查看更多