[英]Spring Boot unit test with SpringSecurity and Mock
Currently I have several unit tests that's working correctly.目前我有几个单元测试可以正常工作。 In my unit test, on init, I have included the following code:
在我的单元测试中,在 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();
}
this worked great, but some authorizations annotations, like @PreAuthorize
are ignored.这很好用,但忽略了一些授权注释,例如
@PreAuthorize
。 (In my WebSecurityConfig, I already added the @EnableGlobalMethodSecurity(prePostEnabled = true)
annotation. (在我的 WebSecurityConfig 中,我已经添加了
@EnableGlobalMethodSecurity(prePostEnabled = true)
注释。
So, after some time, I found the following code:所以,过了一段时间,我找到了以下代码:
@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();
}
and now, the authorization annotations ( @PreAuthorize
) works, but the UsersServices
mock don't.现在,授权注释(
@PreAuthorize
)有效,但UsersServices
模拟无效。 When I call my controller method on unit tests, the real UserServices
was called, not the mock.当我在单元测试中调用我的控制器方法时,调用的是真正的
UserServices
,而不是模拟。
Here is a unit test that mock a 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());
without the standaloneSetup
, the real userServices.getUserAvatar
is called.没有
standaloneSetup
,真正的userServices.getUserAvatar
被调用。
This happens because your WebApplicationContext
is not aware of your UsersController
with mocked UsersServices
.发生这种情况是因为您的
WebApplicationContext
不知道您的UsersController
与UsersServices
。 To fix this you have two options:要解决此问题,您有两个选择:
The first option is to use第一个选项是使用
@MockBean
private UsersServices usersServices;
instead of:代替:
@Mock
private UsersServices usersServices;
This will add mocked bean into application context so that the Spring is aware of it and, thus, will use it instead of a real one.这会将模拟 bean 添加到应用程序上下文中,以便 Spring 知道它,因此将使用它而不是真正的 bean。
The second option is to set your controller directly inside WebApplicationContext
manually.第二个选项是直接在
WebApplicationContext
手动设置控制器。 This option should not be "tried at home", but can be a workaround for cases when you do not have @MockedBean
because of the old spring version:此选项不应“在家尝试”,但可以作为由于旧的 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.