繁体   English   中英

使用 SpringSecurity 和 Mock 进行 Spring Boot 单元测试

[英]Spring Boot unit test with SpringSecurity and Mock

目前我有几个单元测试可以正常工作。 在我的单元测试中,在 init 中,我包含了以下代码:

@Mock
private UsersServices usersServices;

@InjectMocks
private UsersController usersControllers;

@Before
public void init() {
  this.mvc = MockMvcBuilders.standaloneSetup(usuariosController)
                            .addFilter(springSecurityFilterChain)
                            .setControllerAdvice(new UsuariosControllerAdvice(logService)).build();
}

这很好用,但忽略了一些授权注释,例如@PreAuthorize (在我的 WebSecurityConfig 中,我已经添加了@EnableGlobalMethodSecurity(prePostEnabled = true)注释。

所以,过了一段时间,我找到了以下代码:

@Mock
private UsersServices usersServices;

@InjectMocks
private UsersController usersControllers;

@Autowired
private WebApplicationContext wac;

@Before
public void init() {
  this.mvc = MockMvcBuilders
      .webAppContextSetup(wac)
      .addFilter(springSecurityFilterChain)
      apply(SecurityMockMvcConfigurers.springSecurity(springSecurityFilterChain))
      .build();
}

现在,授权注释( @PreAuthorize )有效,但UsersServices模拟无效。 当我在单元测试中调用我的控制器方法时,调用的是真正的UserServices ,而不是模拟。

这是一个模拟UserServices的单元测试:

when(usersServices.getUserAvatar(anyString())).thenReturn(
    CompletableFuture.completedFuture(Optional.empty()));

MvcResult result = mvc.perform(
    get("/api/users/avatar/{login:.+}", "mock.user")
        .header("Authorization", testHelpers.buildJwtToken("USER")))
        .andReturn();

    mvc.perform(asyncDispatch(result))
       .andExpect(status().isNotFound());

没有standaloneSetup ,真正的userServices.getUserAvatar被调用。

发生这种情况是因为您的WebApplicationContext不知道您的UsersControllerUsersServices 要解决此问题,您有两个选择:

第一个选项是使用

@MockBean
private UsersServices usersServices;

代替:

@Mock
private UsersServices usersServices;

这会将模拟 bean 添加到应用程序上下文中,以便 Spring 知道它,因此将使用它而不是真正的 bean。

第二个选项是直接在WebApplicationContext手动设置控制器。 此选项不应“在家尝试”,但可以作为由于旧的 spring 版本而没有@MockedBean情况的解决方法:

AutowireCapableBeanFactory factory = wac.getAutowireCapableBeanFactory();
BeanDefinitionRegistry registry = (BeanDefinitionRegistry) factory;
registry.removeBeanDefinition(beanId);

//create newBeanObj through GenericBeanDefinition

registry.registerBeanDefinition(beanId, newBeanObj);

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM