I try to use the following Annotation to Authenticate in Testing of my Spring Boot 2 Application.
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.METHOD)
@Documented
public @interface MockAuthorize {
String[] roles() default {Role.ROLE_ADMIN};
String username() default "testUser";
}
After research how to call Code before and after custom Annotated Methods I decided to use Spring AOP for that.
@Aspect
public class MockAuthorizeAspect {
@Around("app.annotation.AspectJPointcutStorage.mockAuthorize()")
public Object loginBeforeAndLogoutAfter(ProceedingJoinPoint joinPoint, MockAuthorize mockAuthorize) throws Throwable {
final String[] roles = mockAuthorize.roles();
final String username = mockAuthorize.username();
Set<GrantedAuthority> resolvedRoles = Sets.newLinkedHashSet();
for (String role : roles) {
resolvedRoles.add(new SimpleGrantedAuthority(role));
}
SecurityContextHolder.getContext().setAuthentication(new PreAuthenticatedAuthenticationToken(username, "", resolvedRoles));
final Object proceed = joinPoint.proceed();
AuthentificationService.AuthentificationMock.logout();
return proceed;
}
}
So I added Config to my pom.xml
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
But when I execute my Testing in Debug Mode...
@SpringBootTest
class UserTest {
@Autowired
private UserService userService;
@Autowired
private RoleService roleService;
@Autowired
private MockAuthorizeAspect mockAuthorizeAspect;
private User user = null;
@BeforeEach
void setUp() {
try {
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
user = new User("hansmeier", "password", "Hans", "Meier", "hansimeier@gmx.net", "+4915465656", null);
user.setRoles(Sets.newHashSet(roleService.getByName(Role.ROLE_USER).orElse(null)));
AuthentificationService.AuthentificationMock.logout();
} catch (Exception e) {
//Nothing to do here!
}
}
@AfterEach
void tearDown() {
try {
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
userService.delete(user);
AuthentificationService.AuthentificationMock.logout();
} catch (Exception e) {
//Nothing to do here!
}
}
@Test
@SneakyThrows
void testCreate() {
//GIVEN
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
//WHEN
user = userService.save(user);
//THEN
assertEquals(userService.getByUsernameResolved(user.getUsername()).orElse(null), user);
AuthentificationService.AuthentificationMock.logout();
}
@Test
void testCreateUnauthorized() {
boolean failed = false;
//WHEN
try {
user = userService.save(user);
} catch (AuthenticationCredentialsNotFoundException e) {
failed = true;
}
assertTrue(failed);
}
@Test
@SneakyThrows
void testGetByUsername() {
//GIVEN
AuthentificationService.AuthentificationMock.loginAsAdminOnly();
user = userService.save(user);
//WHEN
final User foundUser = userService.getByUsernameResolved(user.getUsername()).orElse(null);
AuthentificationService.AuthentificationMock.logout();
//THEN
assertEquals(user, foundUser);
}
@Test
@MockAuthorize
void testGetById() {
//GIVEN
user = userService.save(user);
//WHEN
final User foundUser = userService.getById(user.getId()).orElse(null);
//THEN
assertEquals(user, foundUser);
}
@Test
@MockAuthorize
void testGetAll() {
//GIVEN
user = userService.save(user);
//WHEN
final Set<User> allResolved = userService.getAllResolved();
//THEN
for (User u : allResolved) {
if (u.equals(user)) {
assertTrue(true);
return;
}
}
fail("User is not in all Users, something went wrong");
}
}
...the AspectClass is not called and no Exception is thrown, except one from Spring Security Authentication because none is Provided.
So I did research what are necessary and I tried adding a Configuration:
@Configuration
@EnableAspectJAutoProxy
public class AOPConfiguration {
@Bean
public MockAuthorizeAspect mockAuthorizeAspect(){
return new MockAuthorizeAspect();
}
}
My POM:
<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-log4j2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-security</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.1</version>
</dependency>
<dependency>
<groupId>javax.xml.bind</groupId>
<artifactId>jaxb-api</artifactId>
</dependency>
<dependency>
<groupId>joda-time</groupId>
<artifactId>joda-time</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
</dependency>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.18</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-devtools</artifactId>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>28.1-jre</version>
</dependency>
<dependency>
<groupId>org.jetbrains</groupId>
<artifactId>annotations</artifactId>
<version>16.0.2</version>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>javax.annotation</groupId>
<artifactId>jsr250-api</artifactId>
<version>1.0</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-test</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>aspectj-maven-plugin</artifactId>
<version>1.4</version>
<executions>
<execution>
<goals>
<goal>compile</goal>
<goal>test-compile</goal>
</goals>
</execution>
</executions>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.5.1</version>
<configuration>
<source>${maven.compiler.source}</source>
<target>${maven.compiler.target}</target>
</configuration>
</plugin>
</plugins>
</build>
Sadly there were no changes in behavior, so now I hope anyone had faced a similar problem or has an Idea what I missed.