我要说的是,“在单位测试期间,当然不使用试验集装箱”。 速度较慢:用测试集装箱,你需要签发有效标识、编码,然后在MockMvc申请职位处理器(.with(jwt)(
)(你使用)、WebClient mutators和测试说明直接建立Authentication
。
此外,经测试说明,在单位测试除<代码>@以外的其他组成部分时,你可以设定安全等级。 主计长代码>。 例如:
@Service
public class SecuredService {
@PreAuthorize("hasAuthority( NICE )")
String nice() {
return "Dear %s, glad to see you!".formatted(SecurityContextHolder.getContext().getAuthentication().getName());
}
@PreAuthorize("isAuthenticated()")
String hello() {
return "Hello %s.".formatted(SecurityContextHolder.getContext().getAuthentication().getName());
}
}
有了测试集装箱,你需要请求建立安全环境,但在测试这种编号<>@service时,这毫无意义。
我不是MockMvc员额处理员,而是向以下网站提供了资料:。 I published in mers-addons-oauth2-
。
随附“我的”说明,你有不同的选择来测试上述服务(注:与Junnit 5 <代码>@Paraile的兼容性):
- if defining just authorities (and maybe name and
Authentication
type to build), @WithMockAuthentication
is probably enough:
@SpringBootTest(classes = { SecurityConfig.class, MessageService.class })
class MessageServiceTests {
@Autowired
private SecuredService securedService;
@Test
@WithMockAuthentication("BAD_BOY")
void givenUserIsNotGrantedWithNice_whenCallNice_thenThrows() {
assertThrows(Exception.class, () -> securedService.nice());
}
@Test
@WithMockAuthentication(name = "brice", authorities = "NICE")
void givenUserIsNice_whenCallNice_thenReturnsGreeting() {
assertThat(securedService.nice()).isEqualTo("Dear brice, glad to see you!");
}
@ParameterizedTest
@AuthenticationSource(
@WithMockAuthentication(name = "brice", authorities = "NICE"),
@WithMockAuthentication(name = "ch4mp", authorities = { "VERY_NICE", "AUTHOR" }))
void givenUserIsAuthenticated_whenCallHello_thenReturnsGreeting(@ParameterizedAuthentication Authentication auth) {
assertThat(securedService.hello()).isEqualTo("Hello %s.".formatted(auth.getName()));
}
}
- if you want a complete control on all claims, then
@WithJwt
(or @WithOpaqueToken
if you re using introspection) might be better suited:
@AddonsWebmvcComponentTest // omit if you re not using the starter, this loads a minimal subset of spring-addons security conf
@SpringBootTest(classes = { SecurityConfig.class, MessageService.class })
class MessageServiceTests {
@Autowired
private SecuredService securedService;
@Autowired
WithJwt.AuthenticationFactory authFactory;
@Test
@WithJwt("igor.json")
void givenUserIsIgor_whenCallNice_thenThrows() {
assertThrows(Exception.class, () -> securedService.nice());
}
@Test
@WithJwt("brice.json")
void givenUserIsBrice_whenCallNice_thenReturnsGreeting() {
assertThat(securedService.nice()).isEqualTo("Dear brice, glad to see you!");
}
@ParameterizedTest
@MethodSource("identities")
void givenUserIsAuthenticated_whenCallHello_thenReturnsGreeting(@ParameterizedAuthentication Authentication auth) {
assertThat(securedService.hello()).isEqualTo("Hello %s.".formatted(auth.getName()));
}
Stream<AbstractAuthenticationToken> identities() {
return authFactory.authenticationsFrom("brice.json", "igor.json");
}
}
@WithJwt
will search for an authentication converter in your security conf (a Converter<Jwt, ? extends AbstractAuthenticationToken>
as you most probably have defined to turn Keycloak roles into Spring Security authorities) and use it to build an Authentication instance out of a JSON payload in the test class-ath (inspired by a JWT payload or introspection response). So basically, the Authentication instance should be the exact same as with a real authorization server delivering a token with the same claims (name, authorities, Authentication impl, etc.).