WithSecurityContextTestExecutionListener Respects @NestedTestConfiguration

Previously WithSecurityContextTestExecutionListener did not respect
@NestedTestConfiguration.

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

Closes gh-9193
This commit is contained in:
Rob Winch 2020-11-06 15:11:50 -06:00
parent 2b9efccc50
commit 4515c86beb
3 changed files with 49 additions and 22 deletions

View File

@ -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

View File

@ -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<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" })

View File

@ -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() {
}