Browse Source
This commit introduces @DisabledInAotMode in the TestContext framework to support the following use cases. - Disabling AOT build-time processing of a test ApplicationContext -- applicable to any testing framework (JUnit 4, JUnit Jupiter, etc.). - Disabling an entire test class or a single test method at run time when the test suite is run with AOT optimizations enabled -- only applicable to JUnit Jupiter based tests. Closes gh-30834pull/31445/head
10 changed files with 384 additions and 40 deletions
@ -0,0 +1,62 @@
@@ -0,0 +1,62 @@
|
||||
/* |
||||
* Copyright 2002-2023 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.aot; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
import org.junit.jupiter.api.condition.DisabledIf; |
||||
|
||||
/** |
||||
* {@code @DisabledInAotMode} signals that an annotated test class is <em>disabled</em> |
||||
* in Spring AOT (ahead-of-time) mode, which means that the {@code ApplicationContext} |
||||
* for the test class will not be processed for AOT optimizations at build time. |
||||
* |
||||
* <p>If a test class is annotated with {@code @DisabledInAotMode}, all other test |
||||
* classes which specify configuration to load the same {@code ApplicationContext} |
||||
* must also be annotated with {@code @DisabledInAotMode}. Failure to annotate |
||||
* all such test classes will result in a exception, either at build time or |
||||
* run time. |
||||
* |
||||
* <p>When used with JUnit Jupiter based tests, {@code @DisabledInAotMode} also |
||||
* signals that the annotated test class or test method is <em>disabled</em> when |
||||
* running the test suite in Spring AOT mode. When applied at the class level, |
||||
* all test methods within that class will be disabled. In this sense, |
||||
* {@code @DisabledInAotMode} has semantics similar to those of JUnit Jupiter's |
||||
* {@link org.junit.jupiter.api.condition.DisabledInNativeImage @DisabledInNativeImage} |
||||
* annotation. |
||||
* |
||||
* <p>This annotation may be used as a meta-annotation in order to create a |
||||
* custom <em>composed annotation</em> that inherits the semantics of this |
||||
* annotation. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 6.1 |
||||
* @see org.springframework.aot.AotDetector#useGeneratedArtifacts() AotDetector.useGeneratedArtifacts() |
||||
* @see org.junit.jupiter.api.condition.EnabledInNativeImage @EnabledInNativeImage |
||||
* @see org.junit.jupiter.api.condition.DisabledInNativeImage @DisabledInNativeImage |
||||
*/ |
||||
@Target({ElementType.TYPE, ElementType.METHOD}) |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Documented |
||||
@DisabledIf(value = "org.springframework.aot.AotDetector#useGeneratedArtifacts", |
||||
disabledReason = "Disabled in Spring AOT mode") |
||||
public @interface DisabledInAotMode { |
||||
} |
||||
@ -0,0 +1,67 @@
@@ -0,0 +1,67 @@
|
||||
/* |
||||
* Copyright 2002-2023 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.aot.samples.basic; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import org.springframework.aot.AotDetector; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.config.BeanFactoryPostProcessor; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.test.context.aot.DisabledInAotMode; |
||||
import org.springframework.test.context.aot.TestContextAotGenerator; |
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; |
||||
import org.springframework.util.Assert; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* {@code @DisabledInAotMode} test class which verifies that the application context |
||||
* for the test class is skipped during AOT processing. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 6.1 |
||||
*/ |
||||
@SpringJUnitConfig |
||||
@DisabledInAotMode |
||||
public class DisabledInAotProcessingTests { |
||||
|
||||
@Test |
||||
void disabledInAotMode(@Autowired String enigma) { |
||||
assertThat(AotDetector.useGeneratedArtifacts()).as("Should be disabled in AOT mode").isFalse(); |
||||
assertThat(enigma).isEqualTo("puzzle"); |
||||
} |
||||
|
||||
@Configuration |
||||
static class Config { |
||||
|
||||
@Bean |
||||
String enigma() { |
||||
return "puzzle"; |
||||
} |
||||
|
||||
@Bean |
||||
static BeanFactoryPostProcessor bfppBrokenDuringAotProcessing() { |
||||
boolean runningDuringAotProcessing = StackWalker.getInstance().walk(stream -> |
||||
stream.anyMatch(stackFrame -> stackFrame.getClassName().equals(TestContextAotGenerator.class.getName()))); |
||||
|
||||
return beanFactory -> Assert.state(!runningDuringAotProcessing, "Should not be used during AOT processing"); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,72 @@
@@ -0,0 +1,72 @@
|
||||
/* |
||||
* Copyright 2002-2023 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.aot.samples.basic; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import org.springframework.aot.AotDetector; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.test.context.TestPropertySource; |
||||
import org.springframework.test.context.aot.DisabledInAotMode; |
||||
import org.springframework.test.context.aot.samples.common.DefaultMessageService; |
||||
import org.springframework.test.context.aot.samples.common.MessageService; |
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* {@code @DisabledInAotMode} class-level tests. |
||||
* |
||||
* <p>This test class differs from {@link DisabledInAotProcessingTests} whose |
||||
* {@code ApplicationContext} will simply fail during AOT processing. Whereas, |
||||
* the {@code ApplicationContext} for this test class can be properly processed |
||||
* for AOT optimizations, but we want to ensure that we can also disable such a |
||||
* test class in AOT mode if desired. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 6.1 |
||||
* @see DisabledInAotRuntimeMethodLevelTests |
||||
* @see DisabledInAotProcessingTests |
||||
*/ |
||||
@SpringJUnitConfig |
||||
@TestPropertySource(properties = "disabledInAotMode = class-level") |
||||
@DisabledInAotMode |
||||
public class DisabledInAotRuntimeClassLevelTests { |
||||
|
||||
@Test |
||||
void test(@Autowired ApplicationContext context, @Autowired MessageService messageService, |
||||
@Value("${disabledInAotMode}") String disabledInAotMode) { |
||||
|
||||
assertThat(AotDetector.useGeneratedArtifacts()).as("Should be disabled in AOT mode").isFalse(); |
||||
assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); |
||||
assertThat(disabledInAotMode).isEqualTo("class-level"); |
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
static class BasicTestConfiguration { |
||||
|
||||
@Bean |
||||
MessageService defaultMessageService() { |
||||
return new DefaultMessageService(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,74 @@
@@ -0,0 +1,74 @@
|
||||
/* |
||||
* Copyright 2002-2023 the original author or authors. |
||||
* |
||||
* Licensed under the Apache License, Version 2.0 (the "License"); |
||||
* you may not use this file except in compliance with the License. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* https://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.aot.samples.basic; |
||||
|
||||
import org.junit.jupiter.api.Test; |
||||
|
||||
import org.springframework.aot.AotDetector; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.beans.factory.annotation.Value; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.test.context.TestPropertySource; |
||||
import org.springframework.test.context.aot.DisabledInAotMode; |
||||
import org.springframework.test.context.aot.samples.common.DefaultMessageService; |
||||
import org.springframework.test.context.aot.samples.common.MessageService; |
||||
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig; |
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat; |
||||
|
||||
/** |
||||
* {@code @DisabledInAotMode} method-level tests. |
||||
* |
||||
* <p>The {@code ApplicationContext} will still be processed for AOT optimizations |
||||
* and used for the {@link #test} method (in standard JVM mode and in AOT mode), |
||||
* but the {@link #disabledInAotMode()} method will not be executed in AOT mode. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 6.1 |
||||
* @see DisabledInAotRuntimeClassLevelTests |
||||
* @see DisabledInAotProcessingTests |
||||
*/ |
||||
@SpringJUnitConfig |
||||
@TestPropertySource(properties = "disabledInAotMode = method-level") |
||||
public class DisabledInAotRuntimeMethodLevelTests { |
||||
|
||||
@Test |
||||
void test(@Autowired ApplicationContext context, @Autowired MessageService messageService, |
||||
@Value("${disabledInAotMode}") String disabledInAotMode) { |
||||
|
||||
assertThat(messageService.generateMessage()).isEqualTo("Hello, AOT!"); |
||||
assertThat(disabledInAotMode).isEqualTo("method-level"); |
||||
} |
||||
|
||||
@Test |
||||
@DisabledInAotMode |
||||
void disabledInAotMode() { |
||||
assertThat(AotDetector.useGeneratedArtifacts()).as("Should be disabled in AOT mode").isFalse(); |
||||
} |
||||
|
||||
@Configuration(proxyBeanMethods = false) |
||||
static class BasicTestConfiguration { |
||||
|
||||
@Bean |
||||
MessageService defaultMessageService() { |
||||
return new DefaultMessageService(); |
||||
} |
||||
} |
||||
|
||||
} |
||||
Loading…
Reference in new issue