瀏覽代碼

WithSecurityContextTestExecutionListener Respects @NestedTestConfiguration

Previously WithSecurityContextTestExecutionListener did not respect
@NestedTestConfiguration.

This commit switches to using TestContextAnnotationUtils to ensure that
@NestedTestConfiguration is respected.

Closes gh-9193
Rob Winch 4 年之前
父節點
當前提交
4515c86beb

+ 1 - 1
gradle.properties

@@ -1,7 +1,7 @@
 aspectjVersion=1.9.6
 aspectjVersion=1.9.6
 gaeVersion=1.9.82
 gaeVersion=1.9.82
 springJavaformatVersion=0.0.25
 springJavaformatVersion=0.0.25
-springBootVersion=2.4.0-M3
+springBootVersion=2.4.0-SNAPSHOT
 version=5.5.0-SNAPSHOT
 version=5.5.0-SNAPSHOT
 kotlinVersion=1.4.10
 kotlinVersion=1.4.10
 org.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError
 org.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError

+ 13 - 18
test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListener.java

@@ -29,6 +29,7 @@ import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.test.context.TestSecurityContextHolder;
 import org.springframework.security.test.context.TestSecurityContextHolder;
 import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
 import org.springframework.security.test.web.servlet.request.SecurityMockMvcRequestPostProcessors;
 import org.springframework.test.context.TestContext;
 import org.springframework.test.context.TestContext;
+import org.springframework.test.context.TestContextAnnotationUtils;
 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.web.servlet.MockMvc;
 import org.springframework.test.web.servlet.MockMvc;
@@ -60,7 +61,10 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
 	 */
 	 */
 	@Override
 	@Override
 	public void beforeTestMethod(TestContext testContext) {
 	public void beforeTestMethod(TestContext testContext) {
-		TestSecurityContext testSecurityContext = findTestSecurityContext(testContext);
+		TestSecurityContext testSecurityContext = createTestSecurityContext(testContext.getTestMethod(), testContext);
+		if (testSecurityContext == null) {
+			testSecurityContext = createTestSecurityContext(testContext.getTestClass(), testContext);
+		}
 		if (testSecurityContext == null) {
 		if (testSecurityContext == null) {
 			return;
 			return;
 		}
 		}
@@ -73,21 +77,6 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
 		}
 		}
 	}
 	}
 
 
-	private TestSecurityContext findTestSecurityContext(TestContext testContext) {
-		TestSecurityContext testSecurityContext = createTestSecurityContext(testContext.getTestMethod(), testContext);
-		if (testSecurityContext != null) {
-			return testSecurityContext;
-		}
-		for (Class<?> classToSearch = testContext.getTestClass(); classToSearch != null; classToSearch = classToSearch
-				.getEnclosingClass()) {
-			testSecurityContext = createTestSecurityContext(classToSearch, testContext);
-			if (testSecurityContext != null) {
-				return testSecurityContext;
-			}
-		}
-		return null;
-	}
-
 	/**
 	/**
 	 * If configured before test execution sets the SecurityContext
 	 * If configured before test execution sets the SecurityContext
 	 * @since 5.1
 	 * @since 5.1
@@ -108,8 +97,14 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
 	}
 	}
 
 
 	private TestSecurityContext createTestSecurityContext(Class<?> annotated, TestContext context) {
 	private TestSecurityContext createTestSecurityContext(Class<?> annotated, TestContext context) {
-		WithSecurityContext withSecurityContext = AnnotationUtils.findAnnotation(annotated, WithSecurityContext.class);
-		return createTestSecurityContext(annotated, withSecurityContext, context);
+		TestContextAnnotationUtils.AnnotationDescriptor<WithSecurityContext> withSecurityContextDescriptor = TestContextAnnotationUtils
+				.findAnnotationDescriptor(annotated, WithSecurityContext.class);
+		if (withSecurityContextDescriptor == null) {
+			return null;
+		}
+		WithSecurityContext withSecurityContext = withSecurityContextDescriptor.getAnnotation();
+		Class<?> rootDeclaringClass = withSecurityContextDescriptor.getRootDeclaringClass();
+		return createTestSecurityContext(rootDeclaringClass, withSecurityContext, context);
 	}
 	}
 
 
 	@SuppressWarnings({ "rawtypes", "unchecked" })
 	@SuppressWarnings({ "rawtypes", "unchecked" })

+ 35 - 3
test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExcecutionListenerTests.java

@@ -39,6 +39,7 @@ import org.springframework.security.authentication.TestingAuthenticationToken;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContext;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.core.context.SecurityContextHolder;
 import org.springframework.security.test.context.TestSecurityContextHolder;
 import org.springframework.security.test.context.TestSecurityContextHolder;
+import org.springframework.test.context.NestedTestConfiguration;
 import org.springframework.test.context.TestContext;
 import org.springframework.test.context.TestContext;
 import org.springframework.test.context.TestExecutionListener;
 import org.springframework.test.context.TestExecutionListener;
 import org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener;
 import org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener;
@@ -116,6 +117,17 @@ public class WithSecurityContextTestExcecutionListenerTests {
 		assertThat(TestSecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("user");
 		assertThat(TestSecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("user");
 	}
 	}
 
 
+	@Test
+	@SuppressWarnings({ "rawtypes", "unchecked" })
+	public void beforeTestMethodInnerClassWhenOverride() throws Exception {
+		Class testClass = OverrideOuterClass.InnerClass.class;
+		Method testNoAnnotation = ReflectionUtils.findMethod(testClass, "testNoAnnotation");
+		given(this.testContext.getTestClass()).willReturn(testClass);
+		given(this.testContext.getTestMethod()).willReturn(testNoAnnotation);
+		this.listener.beforeTestMethod(this.testContext);
+		assertThat(TestSecurityContextHolder.getContext().getAuthentication()).isNull();
+	}
+
 	// gh-3962
 	// gh-3962
 	@Test
 	@Test
 	public void withSecurityContextAfterSqlScripts() {
 	public void withSecurityContextAfterSqlScripts() {
@@ -191,14 +203,34 @@ public class WithSecurityContextTestExcecutionListenerTests {
 	}
 	}
 
 
 	@WithMockUser
 	@WithMockUser
-	static class OuterClass {
+	class OuterClass {
+
+		class InnerClass {
+
+			void testNoAnnotation() {
+			}
+
+			class InnerInnerClass {
+
+				void testNoAnnotation() {
+				}
+
+			}
+
+		}
+
+	}
+
+	@WithMockUser
+	@NestedTestConfiguration(NestedTestConfiguration.EnclosingConfiguration.OVERRIDE)
+	class OverrideOuterClass {
 
 
-		static class InnerClass {
+		class InnerClass {
 
 
 			void testNoAnnotation() {
 			void testNoAnnotation() {
 			}
 			}
 
 
-			static class InnerInnerClass {
+			class InnerInnerClass {
 
 
 				void testNoAnnotation() {
 				void testNoAnnotation() {
 				}
 				}