WithSecurityContextTestExecutionListener supports generic Annotation

Previously Spring Security's WithSecurityContextTestExecutionListener
allowed a WithSecurityContextFactory<Annotation> to be used. This
was broken in SEC-3074.

This commit ensures that WithSecurityContextFactory<Annotation> is
supported again.

Fixes gh-3837
This commit is contained in:
Rob Winch 2016-05-03 13:07:45 -05:00 committed by Joe Grandja
parent 04a12f49b1
commit 78bf6e2bd5
2 changed files with 79 additions and 6 deletions

View File

@ -71,7 +71,7 @@ public class WithSecurityContextTestExecutionListener extends
if (withSecurityContext != null) {
WithSecurityContextFactory factory = createFactory(withSecurityContext, context);
Class<? extends Annotation> type = (Class<? extends Annotation>) GenericTypeResolver.resolveTypeArgument(factory.getClass(), WithSecurityContextFactory.class);
Annotation annotation = AnnotationUtils.findAnnotation(annotated, type);
Annotation annotation = findAnnotation(annotated, type);
try {
return factory.createSecurityContext(annotation);
}
@ -83,6 +83,23 @@ public class WithSecurityContextTestExecutionListener extends
return null;
}
private Annotation findAnnotation(AnnotatedElement annotated,
Class<? extends Annotation> type) {
Annotation findAnnotation = AnnotationUtils.findAnnotation(annotated, type);
if (findAnnotation != null) {
return findAnnotation;
}
Annotation[] allAnnotations = AnnotationUtils.getAnnotations(annotated);
for (Annotation annotationToTest : allAnnotations) {
WithSecurityContext withSecurityContext = AnnotationUtils.findAnnotation(
annotationToTest.annotationType(), WithSecurityContext.class);
if (withSecurityContext != null) {
return annotationToTest;
}
}
return null;
}
private WithSecurityContextFactory<? extends Annotation> createFactory(
WithSecurityContext withSecurityContext, TestContext testContext) {
Class<? extends WithSecurityContextFactory<? extends Annotation>> clazz = withSecurityContext

View File

@ -15,16 +15,29 @@
*/
package org.springframework.security.test.context.support;
import static org.assertj.core.api.Assertions.*;
import java.lang.annotation.Annotation;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;
import org.springframework.security.authentication.TestingAuthenticationToken;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.util.ReflectionUtils;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
/**
* @author Rob Winch
@ -35,7 +48,12 @@ public class WithSecurityContextTestExecutionListenerTests {
@Before
public void setup() {
listener = new WithSecurityContextTestExecutionListener();
this.listener = new WithSecurityContextTestExecutionListener();
}
@After
public void cleanup() {
SecurityContextHolder.clearContext();
}
// SEC-2709
@ -45,10 +63,48 @@ public class WithSecurityContextTestExecutionListenerTests {
List<TestExecutionListener> listeners = new ArrayList<TestExecutionListener>();
listeners.add(otherListener);
listeners.add(listener);
listeners.add(this.listener);
AnnotationAwareOrderComparator.sort(listeners);
assertThat(listeners).containsSequence(listener, otherListener);
assertThat(listeners).containsSequence(this.listener, otherListener);
}
@Test
// gh-3837
public void handlesGenericAnnotation() throws Exception {
Method method = ReflectionUtils.findMethod(
WithSecurityContextTestExecutionListenerTests.class,
"handlesGenericAnnotationTestMethod");
TestContext testContext = mock(TestContext.class);
when(testContext.getTestMethod()).thenReturn(method);
when(testContext.getApplicationContext())
.thenThrow(new IllegalStateException(""));
this.listener.beforeTestMethod(testContext);
assertThat(SecurityContextHolder.getContext().getAuthentication().getPrincipal())
.isInstanceOf(WithSuperClassWithSecurityContext.class);
}
@WithSuperClassWithSecurityContext
public void handlesGenericAnnotationTestMethod() {
}
@Retention(RetentionPolicy.RUNTIME)
@WithSecurityContext(factory = SuperClassWithSecurityContextFactory.class)
@interface WithSuperClassWithSecurityContext {
String username() default "WithSuperClassWithSecurityContext";
}
static class SuperClassWithSecurityContextFactory
implements WithSecurityContextFactory<Annotation> {
@Override
public SecurityContext createSecurityContext(Annotation annotation) {
SecurityContext context = SecurityContextHolder.createEmptyContext();
context.setAuthentication(new TestingAuthenticationToken(annotation, "NA"));
return context;
}
}
}