SEC-3041: Fix WithSecurityContextTestExecutionListener w/ no ApplicationContext

This commit is contained in:
Rob Winch 2015-07-16 13:13:46 -05:00
parent 0e36f85dab
commit 4cafd575c0
2 changed files with 36 additions and 6 deletions

View File

@ -17,7 +17,9 @@ package org.springframework.security.test.context.support;
import java.lang.annotation.Annotation; import java.lang.annotation.Annotation;
import org.springframework.beans.BeanUtils;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.context.support.StaticApplicationContext;
import org.springframework.core.annotation.AnnotationUtils; import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.core.annotation.Order; import org.springframework.core.annotation.Order;
import org.springframework.security.core.context.SecurityContext; import org.springframework.security.core.context.SecurityContext;
@ -28,7 +30,10 @@ import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestExecutionListener; import org.springframework.test.context.TestExecutionListener;
import org.springframework.test.context.support.AbstractTestExecutionListener; import org.springframework.test.context.support.AbstractTestExecutionListener;
import org.springframework.test.context.support.DependencyInjectionTestExecutionListener; import org.springframework.test.context.support.DependencyInjectionTestExecutionListener;
import org.springframework.test.util.ReflectionTestUtils;
import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MockMvc;
import org.springframework.util.ClassUtils;
import org.springframework.util.ReflectionUtils;
/** /**
* A {@link TestExecutionListener} that will find annotations that are annotated with * A {@link TestExecutionListener} that will find annotations that are annotated with
@ -45,6 +50,7 @@ import org.springframework.test.web.servlet.MockMvc;
public class WithSecurityContextTestExecutionListener extends public class WithSecurityContextTestExecutionListener extends
AbstractTestExecutionListener { AbstractTestExecutionListener {
/** /**
* Sets up the {@link SecurityContext} for each test method. First the specific method * Sets up the {@link SecurityContext} for each test method. First the specific method
* is inspected for a {@link WithSecurityContext} or {@link Annotation} that has * is inspected for a {@link WithSecurityContext} or {@link Annotation} that has
@ -55,12 +61,11 @@ public class WithSecurityContextTestExecutionListener extends
public void beforeTestMethod(TestContext testContext) throws Exception { public void beforeTestMethod(TestContext testContext) throws Exception {
Annotation[] methodAnnotations = AnnotationUtils.getAnnotations(testContext Annotation[] methodAnnotations = AnnotationUtils.getAnnotations(testContext
.getTestMethod()); .getTestMethod());
ApplicationContext context = testContext.getApplicationContext();
SecurityContext securityContext = createSecurityContext(methodAnnotations, SecurityContext securityContext = createSecurityContext(methodAnnotations,
context); testContext);
if (securityContext == null) { if (securityContext == null) {
Annotation[] classAnnotations = testContext.getTestClass().getAnnotations(); Annotation[] classAnnotations = testContext.getTestClass().getAnnotations();
securityContext = createSecurityContext(classAnnotations, context); securityContext = createSecurityContext(classAnnotations, testContext);
} }
if (securityContext != null) { if (securityContext != null) {
TestSecurityContextHolder.setContext(securityContext); TestSecurityContextHolder.setContext(securityContext);
@ -69,7 +74,7 @@ public class WithSecurityContextTestExecutionListener extends
@SuppressWarnings({ "rawtypes", "unchecked" }) @SuppressWarnings({ "rawtypes", "unchecked" })
private SecurityContext createSecurityContext(Annotation[] annotations, private SecurityContext createSecurityContext(Annotation[] annotations,
ApplicationContext context) { TestContext context) {
for (Annotation a : annotations) { for (Annotation a : annotations) {
WithSecurityContext withUser = AnnotationUtils.findAnnotation( WithSecurityContext withUser = AnnotationUtils.findAnnotation(
a.annotationType(), WithSecurityContext.class); a.annotationType(), WithSecurityContext.class);
@ -88,11 +93,14 @@ public class WithSecurityContextTestExecutionListener extends
} }
private WithSecurityContextFactory<? extends Annotation> createFactory( private WithSecurityContextFactory<? extends Annotation> createFactory(
WithSecurityContext withUser, ApplicationContext context) { WithSecurityContext withUser, TestContext testContext) {
Class<? extends WithSecurityContextFactory<? extends Annotation>> clazz = withUser Class<? extends WithSecurityContextFactory<? extends Annotation>> clazz = withUser
.factory(); .factory();
try { try {
return context.getAutowireCapableBeanFactory().createBean(clazz); return testContext.getApplicationContext().getAutowireCapableBeanFactory().createBean(clazz);
}
catch (IllegalStateException e) {
return BeanUtils.instantiateClass(clazz);
} }
catch (Exception e) { catch (Exception e) {
throw new RuntimeException(e); throw new RuntimeException(e);

View File

@ -15,6 +15,8 @@
*/ */
package org.springframework.security.test.context.support; package org.springframework.security.test.context.support;
import static org.fest.assertions.Assertions.*;
import static org.mockito.Mockito.when; import static org.mockito.Mockito.when;
import org.junit.After; import org.junit.After;
@ -27,6 +29,7 @@ import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.context.annotation.AnnotationConfigApplicationContext; import org.springframework.context.annotation.AnnotationConfigApplicationContext;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.security.test.context.TestSecurityContextHolder; import org.springframework.security.test.context.TestSecurityContextHolder;
import org.springframework.test.AssertThrows;
import org.springframework.test.context.TestContext; import org.springframework.test.context.TestContext;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
@ -65,9 +68,28 @@ public class WithSecurityContextTestExcecutionListenerTests {
listener.beforeTestMethod(testContext); listener.beforeTestMethod(testContext);
} }
@Test
@SuppressWarnings({ "rawtypes", "unchecked" })
public void beforeTestMethodNoApplicationContext() throws Exception {
Class testClass = FakeTest.class;
when(testContext.getApplicationContext()).thenThrow(new IllegalStateException());
when(testContext.getTestClass()).thenReturn(testClass);
when(testContext.getTestMethod()).thenReturn(
ReflectionUtils.findMethod(testClass, "testWithMockUser"));
listener.beforeTestMethod(testContext);
assertThat(TestSecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("user");
}
static class FakeTest { static class FakeTest {
public void testNoAnnotation() { public void testNoAnnotation() {
} }
@WithMockUser
public void testWithMockUser() {
}
} }
@Configuration @Configuration