Skip to content

Commit 87d8741

Browse files
committed
WithSecurityContextTestExecutionListener Supports Nested Classes
WithSecurityContextTestExecutionListener now supports nested classes. If the class is nested WithSecurityContext is not found, then the enclosing class is looked at until there is no enclosing class. Closes gh-9179
1 parent d0d655e commit 87d8741

File tree

2 files changed

+60
-9
lines changed

2 files changed

+60
-9
lines changed

Diff for: test/src/main/java/org/springframework/security/test/context/support/WithSecurityContextTestExecutionListener.java

+17-9
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@
3131
import org.springframework.test.context.TestContext;
3232
import org.springframework.test.context.TestExecutionListener;
3333
import org.springframework.test.context.support.AbstractTestExecutionListener;
34-
import org.springframework.test.util.MetaAnnotationUtils;
3534
import org.springframework.test.web.servlet.MockMvc;
3635

3736
/**
@@ -61,10 +60,7 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
6160
*/
6261
@Override
6362
public void beforeTestMethod(TestContext testContext) {
64-
TestSecurityContext testSecurityContext = createTestSecurityContext(testContext.getTestMethod(), testContext);
65-
if (testSecurityContext == null) {
66-
testSecurityContext = createTestSecurityContext(testContext.getTestClass(), testContext);
67-
}
63+
TestSecurityContext testSecurityContext = findTestSecurityContext(testContext);
6864
if (testSecurityContext == null) {
6965
return;
7066
}
@@ -77,6 +73,21 @@ public void beforeTestMethod(TestContext testContext) {
7773
}
7874
}
7975

76+
private TestSecurityContext findTestSecurityContext(TestContext testContext) {
77+
TestSecurityContext testSecurityContext = createTestSecurityContext(testContext.getTestMethod(), testContext);
78+
if (testSecurityContext != null) {
79+
return testSecurityContext;
80+
}
81+
for (Class<?> classToSearch = testContext.getTestClass(); classToSearch != null; classToSearch = classToSearch
82+
.getEnclosingClass()) {
83+
testSecurityContext = createTestSecurityContext(classToSearch, testContext);
84+
if (testSecurityContext != null) {
85+
return testSecurityContext;
86+
}
87+
}
88+
return null;
89+
}
90+
8091
/**
8192
* If configured before test execution sets the SecurityContext
8293
* @since 5.1
@@ -97,10 +108,7 @@ private TestSecurityContext createTestSecurityContext(AnnotatedElement annotated
97108
}
98109

99110
private TestSecurityContext createTestSecurityContext(Class<?> annotated, TestContext context) {
100-
MetaAnnotationUtils.AnnotationDescriptor<WithSecurityContext> withSecurityContextDescriptor = MetaAnnotationUtils
101-
.findAnnotationDescriptor(annotated, WithSecurityContext.class);
102-
WithSecurityContext withSecurityContext = (withSecurityContextDescriptor != null)
103-
? withSecurityContextDescriptor.getAnnotation() : null;
111+
WithSecurityContext withSecurityContext = AnnotationUtils.findAnnotation(annotated, WithSecurityContext.class);
104112
return createTestSecurityContext(annotated, withSecurityContext, context);
105113
}
106114

Diff for: test/src/test/java/org/springframework/security/test/context/support/WithSecurityContextTestExcecutionListenerTests.java

+43
Original file line numberDiff line numberDiff line change
@@ -92,6 +92,30 @@ public void beforeTestMethodNoApplicationContext() throws Exception {
9292
assertThat(TestSecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("user");
9393
}
9494

95+
@Test
96+
@SuppressWarnings({ "rawtypes", "unchecked" })
97+
public void beforeTestMethodInnerClass() throws Exception {
98+
Class testClass = OuterClass.InnerClass.class;
99+
Method testNoAnnotation = ReflectionUtils.findMethod(testClass, "testNoAnnotation");
100+
given(this.testContext.getTestClass()).willReturn(testClass);
101+
given(this.testContext.getTestMethod()).willReturn(testNoAnnotation);
102+
given(this.testContext.getApplicationContext()).willThrow(new IllegalStateException(""));
103+
this.listener.beforeTestMethod(this.testContext);
104+
assertThat(TestSecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("user");
105+
}
106+
107+
@Test
108+
@SuppressWarnings({ "rawtypes", "unchecked" })
109+
public void beforeTestMethodInnerInnerClass() throws Exception {
110+
Class testClass = OuterClass.InnerClass.InnerInnerClass.class;
111+
Method testNoAnnotation = ReflectionUtils.findMethod(testClass, "testNoAnnotation");
112+
given(this.testContext.getTestClass()).willReturn(testClass);
113+
given(this.testContext.getTestMethod()).willReturn(testNoAnnotation);
114+
given(this.testContext.getApplicationContext()).willThrow(new IllegalStateException(""));
115+
this.listener.beforeTestMethod(this.testContext);
116+
assertThat(TestSecurityContextHolder.getContext().getAuthentication().getName()).isEqualTo("user");
117+
}
118+
95119
// gh-3962
96120
@Test
97121
public void withSecurityContextAfterSqlScripts() {
@@ -166,4 +190,23 @@ static class Config {
166190

167191
}
168192

193+
@WithMockUser
194+
static class OuterClass {
195+
196+
static class InnerClass {
197+
198+
void testNoAnnotation() {
199+
}
200+
201+
static class InnerInnerClass {
202+
203+
void testNoAnnotation() {
204+
}
205+
206+
}
207+
208+
}
209+
210+
}
211+
169212
}

0 commit comments

Comments
 (0)