diff --git a/gradle.properties b/gradle.properties index 37be39fb61..ea60eaefea 100644 --- a/gradle.properties +++ b/gradle.properties @@ -1,7 +1,7 @@ aspectjVersion=1.9.6 gaeVersion=1.9.82 springJavaformatVersion=0.0.25 -springBootVersion=2.4.0-M3 +springBootVersion=2.4.0-SNAPSHOT version=5.5.0-SNAPSHOT kotlinVersion=1.4.10 org.gradle.jvmargs=-Xmx3g -XX:MaxPermSize=2048m -XX:+HeapDumpOnOutOfMemoryError diff --git a/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListener.java b/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListener.java index f4a31feec3..b5fa191248 100644 --- a/test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListener.java +++ b/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.web.servlet.request.SecurityMockMvcRequestPostProcessors; import org.springframework.test.context.TestContext; +import org.springframework.test.context.TestContextAnnotationUtils; import org.springframework.test.context.TestExecutionListener; import org.springframework.test.context.support.AbstractTestExecutionListener; import org.springframework.test.web.servlet.MockMvc; @@ -60,7 +61,10 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut */ @Override 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) { 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 * @since 5.1 @@ -108,8 +97,14 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut } private TestSecurityContext createTestSecurityContext(Class annotated, TestContext context) { - WithSecurityContext withSecurityContext = AnnotationUtils.findAnnotation(annotated, WithSecurityContext.class); - return createTestSecurityContext(annotated, withSecurityContext, context); + TestContextAnnotationUtils.AnnotationDescriptor 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" }) diff --git a/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExcecutionListenerTests.java b/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExcecutionListenerTests.java index e29303ffbe..7a96aec512 100644 --- a/test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExcecutionListenerTests.java +++ b/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.SecurityContextHolder; import org.springframework.security.test.context.TestSecurityContextHolder; +import org.springframework.test.context.NestedTestConfiguration; import org.springframework.test.context.TestContext; import org.springframework.test.context.TestExecutionListener; import org.springframework.test.context.jdbc.SqlScriptsTestExecutionListener; @@ -116,6 +117,17 @@ public class WithSecurityContextTestExcecutionListenerTests { 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 @Test public void withSecurityContextAfterSqlScripts() { @@ -191,14 +203,34 @@ public class WithSecurityContextTestExcecutionListenerTests { } @WithMockUser - static class OuterClass { + class OuterClass { - static class InnerClass { + class InnerClass { void testNoAnnotation() { } - static class InnerInnerClass { + class InnerInnerClass { + + void testNoAnnotation() { + } + + } + + } + + } + + @WithMockUser + @NestedTestConfiguration(NestedTestConfiguration.EnclosingConfiguration.OVERRIDE) + class OverrideOuterClass { + + class InnerClass { + + void testNoAnnotation() { + } + + class InnerInnerClass { void testNoAnnotation() { }