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

标签 java spring unit-testing

目前我有几个运行正常的单元测试。 在我的单元测试中,在初始化时,我包含了以下代码:

@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 mock 不。当我在单元测试中调用我的 Controller 方法时,真正的 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不知道您的UsersController与模拟的UsersServices。要解决此问题,您有两个选择:

第一个选项是使用

@MockBean
private UsersServices usersServices;

而不是:

@Mock
private UsersServices usersServices;

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

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

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

//create newBeanObj through GenericBeanDefinition

registry.registerBeanDefinition(beanId, newBeanObj);

关于java - 使用 SpringSecurity 和 Mock 进行 Spring Boot 单元测试,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46981725/

相关文章:

java - 在哪里寻找 java 中的同步争用证据?

java - Eclipse可以像多个源文件夹一样有多个输出文件夹吗

c# - 对具有不同参数的相同方法调用的最小起订量期望

java - Spring如何为@RestController自动将对象转换为json

java - bean标签的parent属性是否相当于Java中的继承?

javascript - 对象中的测试元素是空的,开玩笑

ruby-on-rails - 如何有效测试未认证用户流量?

java - LWJGL OpenGL - 从 3d 点到屏幕中心的线

java - 测试 Spring @MVC 注解

spring - 从 Spring 4.1.6 升级到 4.2.4 突然出现 TransactionRequiredException