In many of my integration tests, I have to create Entities with a custom security context. Then within tests I use another security context to check for example the access rights. So I created a new annotation:
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = CustomSecurityContextFactory.class)
public @interface WithCustomUser {
String username();
String[] roles() default {"USER"};
}
This is the CustomSecurityContextFactory
class:
@Component
@RequiredArgsConstructor
public class CustomSecurityContextFactory implements WithSecurityContextFactory<WithCustomUser> {
// dependencies
@Override
public SecurityContext createSecurityContext(WithCustomUser withCustomUser) {
SecurityContext context = SecurityContextHolder.createEmptyContext();
OAuth2AccessToken token = buildToken();
Employee employee = employeeService.findByUsername(withCustomUser.username());
Map<String, Object> attributes = new HashMap<>();
attributes.put("username", withCustomUser.username());
List<String> roles = List.of(withCustomUser.roles());
List<GrantedAuthority> authorities = buildAuthorities(roles, attributes);
employee.setAuthorities(authorities);
employee.setUsername(withCustomUser.username());
employee.setPassword(token.getTokenValue());
UsernamePasswordAuthenticationToken authentication =
new UsernamePasswordAuthenticationToken(employee, token.getTokenValue(), authorities);
context.setAuthentication(authentication);
return context;
}
}
I can now easily use the annotation above test methods like this:
@Test
@WithCustomUser(username = "myUsername")
void simpleTest() {
Order order = orderService.createOrder();
assertThat(order.getEmployee().getUsername()).isEqualTo("myUsername");
}
This works great. but I would like to create the order in beforeAll
method and use it in the tests. something like this:
@BeforeAll
@WithCustomUser(username = "myUsername")
void beforeAllNonStatic() {
Order order = orderService.createOrder();
}
But this obviously doesn't work. when it tries to create the order, employee is null. I currently use static mocking in beforeAll method and that works. but is there a way to make the annotation work? Am I using the annotation at the wrong place?