2020import java .lang .reflect .AnnotatedElement ;
2121import java .util .function .Supplier ;
2222
23- import org .jspecify .annotations .NullUnmarked ;
2423import org .jspecify .annotations .Nullable ;
2524
2625import org .springframework .beans .BeanUtils ;
2726import org .springframework .context .ApplicationContext ;
2827import org .springframework .core .GenericTypeResolver ;
2928import org .springframework .core .annotation .AnnotatedElementUtils ;
3029import org .springframework .core .annotation .AnnotationUtils ;
30+ import org .springframework .core .annotation .MergedAnnotation ;
31+ import org .springframework .core .annotation .MergedAnnotations ;
3132import org .springframework .core .convert .converter .Converter ;
3233import org .springframework .security .core .context .SecurityContext ;
3334import org .springframework .security .core .context .SecurityContextHolder ;
4041import org .springframework .test .context .TestExecutionListener ;
4142import org .springframework .test .context .support .AbstractTestExecutionListener ;
4243import org .springframework .test .web .servlet .MockMvc ;
44+ import org .springframework .util .Assert ;
4345
4446/**
4547 * A {@link TestExecutionListener} that will find annotations that are annotated with
@@ -79,7 +81,6 @@ public class WithSecurityContextTestExecutionListener extends AbstractTestExecut
7981 * {@link WithSecurityContext} on it. If that is not found, the class is inspected. If
8082 * still not found, then no {@link SecurityContext} is populated.
8183 */
82- @ NullUnmarked
8384 @ Override
8485 public void beforeTestMethod (TestContext testContext ) {
8586 TestSecurityContext testSecurityContext = createTestSecurityContext (testContext .getTestMethod (), testContext );
@@ -102,7 +103,6 @@ public void beforeTestMethod(TestContext testContext) {
102103 * If configured before test execution sets the SecurityContext
103104 * @since 5.1
104105 */
105- @ NullUnmarked
106106 @ Override
107107 public void beforeTestExecution (TestContext testContext ) {
108108 Supplier <SecurityContext > supplier = (Supplier <SecurityContext >) testContext
@@ -129,7 +129,6 @@ public void beforeTestExecution(TestContext testContext) {
129129 return createTestSecurityContext (rootDeclaringClass , withSecurityContext , context );
130130 }
131131
132- @ NullUnmarked
133132 @ SuppressWarnings ({ "rawtypes" , "unchecked" })
134133 private @ Nullable TestSecurityContext createTestSecurityContext (AnnotatedElement annotated ,
135134 @ Nullable WithSecurityContext withSecurityContext , TestContext context ) {
@@ -140,7 +139,9 @@ public void beforeTestExecution(TestContext testContext) {
140139 WithSecurityContextFactory factory = createFactory (withSecurityContext , context );
141140 Class <? extends Annotation > type = (Class <? extends Annotation >) GenericTypeResolver
142141 .resolveTypeArgument (factory .getClass (), WithSecurityContextFactory .class );
142+ Assert .isTrue (type != null , factory .getClass () + " must specify a Type argument" );
143143 Annotation annotation = findAnnotation (annotated , type );
144+ Assert .isTrue (annotation != null , "No annotation found for " + type + " on " + annotated );
144145 Supplier <SecurityContext > supplier = () -> {
145146 try {
146147 return factory .createSecurityContext (annotation );
@@ -153,22 +154,23 @@ public void beforeTestExecution(TestContext testContext) {
153154 return new TestSecurityContext (supplier , initialize );
154155 }
155156
156- @ NullUnmarked
157- private @ Nullable Annotation findAnnotation (AnnotatedElement annotated ,
158- @ Nullable Class <? extends Annotation > type ) {
157+ private @ Nullable Annotation findAnnotation (AnnotatedElement annotated , Class <? extends Annotation > type ) {
159158 Annotation findAnnotation = AnnotatedElementUtils .findMergedAnnotation (annotated , type );
160159 if (findAnnotation != null ) {
161160 return findAnnotation ;
162161 }
163- Annotation [] allAnnotations = AnnotationUtils .getAnnotations (annotated );
164- for (Annotation annotationToTest : allAnnotations ) {
165- WithSecurityContext withSecurityContext = AnnotationUtils .findAnnotation (annotationToTest .annotationType (),
166- WithSecurityContext .class );
167- if (withSecurityContext != null ) {
168- return annotationToTest ;
169- }
170- }
171- return null ;
162+ MergedAnnotations allAnnotations = MergedAnnotations .from (annotated );
163+ // @formatter:off
164+ return allAnnotations .stream ()
165+ .filter ((annotationToTest ) -> {
166+ WithSecurityContext withSecurityContext = AnnotationUtils .findAnnotation (annotationToTest .getType (),
167+ WithSecurityContext .class );
168+ return withSecurityContext != null ;
169+ })
170+ .map (MergedAnnotation ::synthesize )
171+ .findFirst ()
172+ .orElse (null );
173+ // @formatter:on
172174 }
173175
174176 private WithSecurityContextFactory <? extends Annotation > createFactory (WithSecurityContext withSecurityContext ,
@@ -189,7 +191,6 @@ private WithSecurityContextFactory<? extends Annotation> createFactory(WithSecur
189191 * Clears out the {@link TestSecurityContextHolder} and the
190192 * {@link SecurityContextHolder} after each test method.
191193 */
192- @ NullUnmarked
193194 @ Override
194195 public void afterTestMethod (TestContext testContext ) {
195196 this .securityContextHolderStrategyConverter .convert (testContext ).clearContext ();
0 commit comments