提交 873fc53a 编写于 作者: S Sam Brannen

Introduce support for JUnit 5 in the TestContext framework

This commit introduces initial support for JUnit Jupiter (i.e., the new
programming and extension models in JUnit 5) in the Spring TestContext
Framework.

Specifically, this commit introduces the following.

- SpringExtension: an implementation of multiple extension APIs from
  JUnit Jupiter that provides full support for the existing feature set
  of the Spring TestContext Framework. This support is enabled via
  @ExtendWith(SpringExtension.class).

- @SpringJUnitConfig: a composed annotation that combines
  @ExtendWith(SpringExtension.class) from JUnit Jupiter with
  @ContextConfiguration from the Spring TestContext Framework.

- @SpringJUnitWebConfig: a composed annotation that combines
  @ExtendWith(SpringExtension.class) from JUnit Jupiter with
  @ContextConfiguration and @WebAppConfiguration from the Spring
  TestContext Framework.

Issue: SPR-13575
上级 54e3ea8d
......@@ -60,6 +60,8 @@ configure(allprojects) { project ->
ext.jrubyVersion = "1.7.25" // JRuby 9000 only supported through JSR-223 (StandardScriptFactory)
ext.jtaVersion = "1.2"
ext.junitVersion = "4.12"
ext.junitJupiterVersion = '5.0.0-SNAPSHOT'
ext.junitPlatformVersion = '1.0.0-SNAPSHOT'
ext.log4jVersion = "1.2.17"
ext.nettyVersion = "4.1.1.Final"
ext.okhttpVersion = "2.7.5"
......@@ -131,6 +133,8 @@ configure(allprojects) { project ->
repositories {
maven { url "https://repo.spring.io/libs-release" }
// For JUnit Platform and Jupiter snapshots:
maven { url 'https://oss.sonatype.org/content/repositories/snapshots' }
}
dependencies {
......@@ -993,6 +997,7 @@ project("spring-test") {
optional(project(":spring-webmvc-portlet"))
optional(project(":spring-websocket"))
optional("junit:junit:${junitVersion}")
optional("org.junit.jupiter:junit-jupiter-api:${junitJupiterVersion}")
optional("org.testng:testng:${testngVersion}")
optional("javax.inject:javax.inject:1")
optional("javax.servlet:javax.servlet-api:3.0.1")
......@@ -1020,6 +1025,8 @@ project("spring-test") {
testCompile("org.hibernate:hibernate-core:${hibernate4Version}")
testCompile("org.hibernate:hibernate-entitymanager:${hibernate4Version}")
testCompile("org.hibernate:hibernate-validator:${hibval5Version}")
// Enable use of the JUnitPlatform Runner
testCompile("org.junit.platform:junit-platform-runner:${junitPlatformVersion}")
testCompile("com.thoughtworks.xstream:xstream:${xstreamVersion}")
testCompile("com.fasterxml.jackson.core:jackson-databind:${jackson2Version}")
testCompile("com.rometools:rome:${romeVersion}")
......@@ -1034,7 +1041,9 @@ project("spring-test") {
testCompile("org.slf4j:slf4j-jcl:${slf4jVersion}")
testCompile("org.apache.httpcomponents:httpclient:${httpclientVersion}")
testCompile("javax.cache:cache-api:1.0.0")
testRuntime("org.junit.jupiter:junit-jupiter-engine:${junitJupiterVersion}")
testRuntime("log4j:log4j:${log4jVersion}")
testRuntime("org.ehcache:ehcache:${ehcache3Version}")
testRuntime("org.terracotta:management-model:2.0.0")
}
......@@ -1053,7 +1062,9 @@ project("spring-test") {
description = 'Runs JUnit tests.'
dependsOn testNG
useJUnit()
exclude "**/testng/**/*.*"
scanForTestClasses = false
include(['**/*Tests.class', '**/*Test.class', '**/SpringJUnitJupiterTestSuite.class'])
exclude(['**/testng/**/*.*'])
}
task aggregateTestReports(type: TestReport) {
......
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.ContainerExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.api.extension.TestExtensionContext;
import org.junit.jupiter.api.extension.TestInstancePostProcessor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.test.context.TestContextManager;
import org.springframework.test.context.junit.jupiter.support.ParameterAutowireUtils;
import org.springframework.util.Assert;
/**
* {@code SpringExtension} integrates the <em>Spring TestContext Framework</em>
* into JUnit 5's <em>Jupiter</em> programming model.
*
* <p>To use this class, simply annotate a JUnit Jupiter based test class with
* {@code @ExtendWith(SpringExtension.class)}.
*
* @author Sam Brannen
* @since 5.0
* @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig
* @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig
* @see org.springframework.test.context.TestContextManager
*/
public class SpringExtension implements BeforeAllCallback, AfterAllCallback, TestInstancePostProcessor,
BeforeEachCallback, AfterEachCallback, ParameterResolver {
/**
* {@link Namespace} in which {@code TestContextManagers} are stored, keyed
* by test class.
*/
private static final Namespace namespace = Namespace.create(SpringExtension.class);
/**
* Delegates to {@link TestContextManager#beforeTestClass}.
*/
@Override
public void beforeAll(ContainerExtensionContext context) throws Exception {
getTestContextManager(context).beforeTestClass();
}
/**
* Delegates to {@link TestContextManager#afterTestClass}.
*/
@Override
public void afterAll(ContainerExtensionContext context) throws Exception {
try {
getTestContextManager(context).afterTestClass();
}
finally {
context.getStore(namespace).remove(context.getTestClass().get());
}
}
/**
* Delegates to {@link TestContextManager#prepareTestInstance}.
*/
@Override
public void postProcessTestInstance(Object testInstance, ExtensionContext context) throws Exception {
getTestContextManager(context).prepareTestInstance(testInstance);
}
/**
* Delegates to {@link TestContextManager#beforeTestMethod}.
*/
@Override
public void beforeEach(TestExtensionContext context) throws Exception {
Object testInstance = context.getTestInstance();
Method testMethod = context.getTestMethod().get();
getTestContextManager(context).beforeTestMethod(testInstance, testMethod);
}
/**
* Delegates to {@link TestContextManager#afterTestMethod}.
*/
@Override
public void afterEach(TestExtensionContext context) throws Exception {
Object testInstance = context.getTestInstance();
Method testMethod = context.getTestMethod().get();
Throwable testException = context.getTestException().orElse(null);
getTestContextManager(context).afterTestMethod(testInstance, testMethod, testException);
}
/**
* Determine if the value for the {@link Parameter} in the supplied
* {@link ParameterContext} should be autowired from the test's
* {@link ApplicationContext}.
* <p>Returns {@code true} if the parameter is declared in a {@link Constructor}
* that is annotated with {@link Autowired @Autowired} and otherwise delegates
* to {@link ParameterAutowireUtils#isAutowirable}.
* <p><strong>WARNING</strong>: if the parameter is declared in a {@code Constructor}
* that is annotated with {@code @Autowired}, Spring will assume the responsibility
* for resolving all parameters in the constructor. Consequently, no other
* registered {@link ParameterResolver} will be able to resolve parameters.
*
* @see #resolve
* @see ParameterAutowireUtils#isAutowirable
*/
@Override
public boolean supports(ParameterContext parameterContext, ExtensionContext extensionContext) {
Parameter parameter = parameterContext.getParameter();
Executable executable = parameter.getDeclaringExecutable();
return (executable instanceof Constructor && AnnotatedElementUtils.hasAnnotation(executable, Autowired.class))
|| ParameterAutowireUtils.isAutowirable(parameter);
}
/**
* Resolve a value for the {@link Parameter} in the supplied
* {@link ParameterContext} by retrieving the corresponding dependency
* from the test's {@link ApplicationContext}.
* <p>Delegates to {@link ParameterAutowireUtils#resolveDependency}.
* @see #supports
* @see ParameterAutowireUtils#resolveDependency
*/
@Override
public Object resolve(ParameterContext parameterContext, ExtensionContext extensionContext) {
Parameter parameter = parameterContext.getParameter();
Class<?> testClass = extensionContext.getTestClass().get();
ApplicationContext applicationContext = getApplicationContext(extensionContext);
return ParameterAutowireUtils.resolveDependency(parameter, testClass, applicationContext);
}
/**
* Get the {@link ApplicationContext} associated with the supplied
* {@code ExtensionContext}.
* @param context the current {@code ExtensionContext}; never {@code null}
* @return the application context
* @throws IllegalStateException if an error occurs while retrieving the
* application context
* @see org.springframework.test.context.TestContext#getApplicationContext()
*/
private ApplicationContext getApplicationContext(ExtensionContext context) {
return getTestContextManager(context).getTestContext().getApplicationContext();
}
/**
* Get the {@link TestContextManager} associated with the supplied
* {@code ExtensionContext}.
* @return the {@code TestContextManager}; never {@code null}
*/
private TestContextManager getTestContextManager(ExtensionContext context) {
Assert.notNull(context, "ExtensionContext must not be null");
Class<?> testClass = context.getTestClass().get();
Store store = context.getStore(namespace);
return store.getOrComputeIfAbsent(testClass, TestContextManager::new, TestContextManager.class);
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.AliasFor;
import org.springframework.test.context.ContextConfiguration;
/**
* {@code @SpringJUnitConfig} is a <em>composed annotation</em> that combines
* {@link ExtendWith @ExtendWith(SpringExtension.class)} from JUnit Jupiter with
* {@link ContextConfiguration @ContextConfiguration} from the <em>Spring TestContext
* Framework</em>.
*
* @author Sam Brannen
* @since 5.0
* @see ExtendWith
* @see SpringExtension
* @see ContextConfiguration
* @see org.springframework.test.context.junit.jupiter.web.SpringJUnitWebConfig
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SpringJUnitConfig {
/**
* Alias for {@link ContextConfiguration#classes}.
*/
@AliasFor(annotation = ContextConfiguration.class, attribute = "classes")
Class<?>[] value() default {};
/**
* Alias for {@link ContextConfiguration#classes}.
*/
@AliasFor(annotation = ContextConfiguration.class)
Class<?>[] classes() default {};
/**
* Alias for {@link ContextConfiguration#locations}.
*/
@AliasFor(annotation = ContextConfiguration.class)
String[] locations() default {};
/**
* Alias for {@link ContextConfiguration#initializers}.
*/
@AliasFor(annotation = ContextConfiguration.class)
Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers() default {};
/**
* Alias for {@link ContextConfiguration#inheritLocations}.
*/
@AliasFor(annotation = ContextConfiguration.class)
boolean inheritLocations() default true;
/**
* Alias for {@link ContextConfiguration#inheritInitializers}.
*/
@AliasFor(annotation = ContextConfiguration.class)
boolean inheritInitializers() default true;
/**
* Alias for {@link ContextConfiguration#name}.
*/
@AliasFor(annotation = ContextConfiguration.class)
String name() default "";
}
/**
* Core support for integrating the <em>Spring TestContext Framework</em>
* with the JUnit Jupiter extension model in JUnit 5.
*/
package org.springframework.test.context.junit.jupiter;
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.support;
import java.lang.reflect.Constructor;
import java.lang.reflect.Executable;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.SynthesizingMethodParameter;
import org.springframework.util.Assert;
/**
* Factory for creating {@link MethodParameter} instances from Java 8
* {@link Parameter Parameters}.
*
* @author Sam Brannen
* @since 5.0
* @see ParameterAutowireUtils
* @see MethodParameter
* @see SynthesizingMethodParameter
* @see #createMethodParameter(Parameter)
* @see #createSynthesizingMethodParameter(Parameter)
*/
public abstract class MethodParameterFactory {
private MethodParameterFactory() {
/* no-op */
}
/**
* Create a standard {@link MethodParameter} from the supplied {@link Parameter}.
* <p>Supports parameters declared in methods and constructors.
* @param parameter the parameter to create a {@code MethodParameter} for;
* never {@code null}
* @return a new {@code MethodParameter}
* @see #createSynthesizingMethodParameter(Parameter)
*/
public static MethodParameter createMethodParameter(Parameter parameter) {
Assert.notNull(parameter, "Parameter must not be null");
Executable executable = parameter.getDeclaringExecutable();
if (executable instanceof Method) {
return new MethodParameter((Method) executable, getIndex(parameter));
}
// else
return new MethodParameter((Constructor<?>) executable, getIndex(parameter));
}
/**
* Create a {@link SynthesizingMethodParameter} from the supplied {@link Parameter}.
* <p>Supports parameters declared in methods.
* @param parameter the parameter to create a {@code SynthesizingMethodParameter}
* for; never {@code null}
* @return a new {@code SynthesizingMethodParameter}
* @throws UnsupportedOperationException if the supplied parameter is declared
* in a constructor
* @see #createMethodParameter(Parameter)
*/
public static SynthesizingMethodParameter createSynthesizingMethodParameter(Parameter parameter) {
Assert.notNull(parameter, "Parameter must not be null");
Executable executable = parameter.getDeclaringExecutable();
if (executable instanceof Method) {
return new SynthesizingMethodParameter((Method) executable, getIndex(parameter));
}
// else
throw new UnsupportedOperationException(
"Cannot create a SynthesizingMethodParameter for a constructor parameter: " + parameter);
}
private static int getIndex(Parameter parameter) {
Assert.notNull(parameter, "Parameter must not be null");
Executable executable = parameter.getDeclaringExecutable();
Parameter[] parameters = executable.getParameters();
for (int i = 0; i < parameters.length; i++) {
if (parameters[i] == parameter) {
return i;
}
}
throw new IllegalStateException(String.format("Failed to resolve index of parameter [%s] in executable [%s]",
parameter, executable.toGenericString()));
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.support;
import java.lang.annotation.Annotation;
import java.lang.reflect.AnnotatedElement;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.Optional;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.context.ApplicationContext;
import org.springframework.core.MethodParameter;
import org.springframework.core.annotation.AnnotatedElementUtils;
import static org.springframework.core.annotation.AnnotatedElementUtils.hasAnnotation;
/**
* Collection of utilities related to autowiring of individual method parameters.
*
* @author Sam Brannen
* @since 5.0
* @see MethodParameterFactory
* @see #isAutowirable(Parameter)
* @see #resolveDependency(Parameter, Class, ApplicationContext)
*/
public abstract class ParameterAutowireUtils {
private ParameterAutowireUtils() {
/* no-op */
}
/**
* Determine if the supplied {@link Parameter} can potentially be
* autowired from an {@link ApplicationContext}.
* <p>Returns {@code true} if the supplied parameter is of type
* {@link ApplicationContext} (or a sub-type thereof) or is annotated or
* meta-annotated with {@link Autowired @Autowired},
* {@link Qualifier @Qualifier}, or {@link Value @Value}.
* @see #resolveDependency(Parameter, Class, ApplicationContext)
*/
public static boolean isAutowirable(Parameter parameter) {
return ApplicationContext.class.isAssignableFrom(parameter.getType())
|| hasAnnotation(parameter, Autowired.class)
|| hasAnnotation(parameter, Qualifier.class)
|| hasAnnotation(parameter, Value.class);
}
/**
* Resolve the dependency for the supplied {@link Parameter} from the
* supplied {@link ApplicationContext}.
* <p>Provides comprehensive autowiring support for individual method parameters
* on par with Spring's dependency injection facilities for autowired fields and
* methods, including support for {@link Autowired @Autowired},
* {@link Qualifier @Qualifier}, and {@link Value @Value} with support for property
* placeholders and SpEL expressions in {@code @Value} declarations.
* <p>The dependency is required unless the parameter is annotated with
* {@link Autowired @Autowired} with the {@link Autowired#required required}
* flag set to {@code false}.
* <p>If an explicit <em>qualifier</em> is not declared, the name of the parameter
* will be used as the qualifier for resolving ambiguities.
* @param parameter the parameter whose dependency should be resolved
* @param containingClass the concrete class that contains the parameter; this may
* differ from the class that declares the parameter in that it may be a subclass
* thereof, potentially substituting type variables
* @param applicationContext the application context from which to resolve the
* dependency
* @return the resolved object, or {@code null} if none found
* @throws BeansException if dependency resolution failed
* @see #isAutowirable(Parameter)
* @see Autowired#required
* @see MethodParameterFactory#createSynthesizingMethodParameter(Parameter)
* @see AutowireCapableBeanFactory#resolveDependency(DependencyDescriptor, String)
*/
public static Object resolveDependency(Parameter parameter, Class<?> containingClass,
ApplicationContext applicationContext) {
boolean required = findMergedAnnotation(parameter, Autowired.class).map(Autowired::required).orElse(true);
MethodParameter methodParameter = (parameter.getDeclaringExecutable() instanceof Method
? MethodParameterFactory.createSynthesizingMethodParameter(parameter)
: MethodParameterFactory.createMethodParameter(parameter));
DependencyDescriptor descriptor = new DependencyDescriptor(methodParameter, required);
descriptor.setContainingClass(containingClass);
return applicationContext.getAutowireCapableBeanFactory().resolveDependency(descriptor, null);
}
private static <A extends Annotation> Optional<A> findMergedAnnotation(AnnotatedElement element,
Class<A> annotationType) {
return Optional.ofNullable(AnnotatedElementUtils.findMergedAnnotation(element, annotationType));
}
}
/**
* Internal support classes for integrating the <em>Spring TestContext Framework</em>
* with the JUnit Jupiter extension model in JUnit 5.
*/
package org.springframework.test.context.junit.jupiter.support;
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.web;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.context.ApplicationContextInitializer;
import org.springframework.context.ConfigurableApplicationContext;
import org.springframework.core.annotation.AliasFor;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.web.WebAppConfiguration;
/**
* {@code @SpringJUnitWebConfig} is a <em>composed annotation</em> that combines
* {@link ExtendWith @ExtendWith(SpringExtension.class)} from JUnit Jupiter with
* {@link ContextConfiguration @ContextConfiguration} and
* {@link WebAppConfiguration @WebAppConfiguration} from the <em>Spring TestContext
* Framework</em>.
*
* @author Sam Brannen
* @since 5.0
* @see ExtendWith
* @see SpringExtension
* @see ContextConfiguration
* @see WebAppConfiguration
* @see org.springframework.test.context.junit.jupiter.SpringJUnitConfig
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration
@WebAppConfiguration
@Documented
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
public @interface SpringJUnitWebConfig {
/**
* Alias for {@link ContextConfiguration#classes}.
*/
@AliasFor(annotation = ContextConfiguration.class, attribute = "classes")
Class<?>[] value() default {};
/**
* Alias for {@link ContextConfiguration#classes}.
*/
@AliasFor(annotation = ContextConfiguration.class)
Class<?>[] classes() default {};
/**
* Alias for {@link ContextConfiguration#locations}.
*/
@AliasFor(annotation = ContextConfiguration.class)
String[] locations() default {};
/**
* Alias for {@link ContextConfiguration#initializers}.
*/
@AliasFor(annotation = ContextConfiguration.class)
Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>[] initializers() default {};
/**
* Alias for {@link ContextConfiguration#inheritLocations}.
*/
@AliasFor(annotation = ContextConfiguration.class)
boolean inheritLocations() default true;
/**
* Alias for {@link ContextConfiguration#inheritInitializers}.
*/
@AliasFor(annotation = ContextConfiguration.class)
boolean inheritInitializers() default true;
/**
* Alias for {@link ContextConfiguration#name}.
*/
@AliasFor(annotation = ContextConfiguration.class)
String name() default "";
/**
* Alias for {@link WebAppConfiguration#value}.
*/
@AliasFor(annotation = WebAppConfiguration.class, attribute = "value")
String resourcePath() default "src/main/webapp";
}
/**
* Web support for integrating the <em>Spring TestContext Framework</em>
* with the JUnit Jupiter extension model in JUnit 5.
*/
package org.springframework.test.context.junit.jupiter.web;
/*
* Copyright 2002-2016 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
*
* http://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.junit;
import org.junit.platform.runner.IncludeEngines;
import org.junit.platform.runner.JUnitPlatform;
import org.junit.platform.runner.SelectPackages;
import org.junit.runner.RunWith;
/**
* JUnit 4 based test suite for tests that involve the Spring TestContext
* Framework and JUnit Jupiter (a.k.a., JUnit 5).
*
* <p>This class intentionally does not reside in the "jupiter" package
* so that the entire "jupiter" package can be excluded from the Gradle
* build. This class is therefore responsible for executing all JUnit
* Jupiter based tests in Spring's official test suite.
*
* @author Sam Brannen
* @since 5.0
*/
@RunWith(JUnitPlatform.class)
@IncludeEngines("junit-jupiter")
@SelectPackages("org.springframework.test.context.junit.jupiter")
public class SpringJUnitJupiterTestSuite {
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter;
import java.util.List;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.SpringJUnitJupiterTestSuite;
import org.springframework.test.context.junit.jupiter.comics.Person;
import static org.junit.jupiter.api.Assertions.*;
/**
* Integration tests which demonstrate the composability of annotations from
* JUnit Jupiter and the Spring TestContext Framework.
*
* <p>Note that {@link SpringJUnitConfig @SpringJUnitConfig} is meta-annotated
* with JUnit Jupiter's {@link ExtendWith @ExtendWith} <b>and</b> Spring's
* {@link ContextConfiguration @ContextConfiguration}.
*
* <p>To run these tests in an IDE, simply run {@link SpringJUnitJupiterTestSuite}
* as a JUnit 4 test.
*
* @author Sam Brannen
* @since 5.0
* @see SpringExtension
* @see SpringJUnitConfig
* @see SpringExtensionTestCase
*/
@SpringJUnitConfig(TestConfig.class)
@DisplayName("@SpringJUnitConfig Tests")
class ComposedSpringExtensionTestCase {
@Autowired
Person dilbert;
@Autowired
List<Person> people;
@Test
@DisplayName("ApplicationContext injected into method")
void applicationContextInjected(ApplicationContext applicationContext) {
assertNotNull(applicationContext, "ApplicationContext should have been injected into method by Spring");
assertEquals(dilbert, applicationContext.getBean("dilbert", Person.class));
}
@Test
@DisplayName("Spring @Beans injected into fields")
void springBeansInjected() {
assertNotNull(dilbert, "Person should have been @Autowired by Spring");
assertEquals("Dilbert", dilbert.getName(), "Person's name");
assertEquals(2, people.size(), "Number of Person objects in context");
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter;
import java.util.List;
import java.util.Optional;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.TestReporter;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.SpringJUnitJupiterTestSuite;
import org.springframework.test.context.junit.jupiter.comics.Cat;
import org.springframework.test.context.junit.jupiter.comics.Dog;
import org.springframework.test.context.junit.jupiter.comics.Person;
import static org.junit.jupiter.api.Assertions.*;
/**
* Integration tests which demonstrate that the Spring TestContext Framework can
* be used with JUnit Jupiter via the {@link SpringExtension}.
*
* <p>To run these tests in an IDE, simply run {@link SpringJUnitJupiterTestSuite}
* as a JUnit 4 test.
*
* @author Sam Brannen
* @since 5.0
* @see SpringExtension
* @see ComposedSpringExtensionTestCase
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = TestConfig.class)
@TestPropertySource(properties = "enigma = 42")
class SpringExtensionTestCase {
@Autowired
Person dilbert;
@Autowired
List<Person> people;
@Autowired
Dog dog;
@Autowired
Cat cat;
@Autowired
List<Cat> cats;
@Value("${enigma}")
Integer enigma;
@Test
void applicationContextInjectedIntoMethod(ApplicationContext applicationContext) {
assertNotNull(applicationContext, "ApplicationContext should have been injected by Spring");
assertEquals(this.dilbert, applicationContext.getBean("dilbert", Person.class));
}
@Test
void genericApplicationContextInjectedIntoMethod(GenericApplicationContext applicationContext) {
assertNotNull(applicationContext, "GenericApplicationContext should have been injected by Spring");
assertEquals(this.dilbert, applicationContext.getBean("dilbert", Person.class));
}
@Test
void autowiredFields() {
assertNotNull(this.dilbert, "Dilbert should have been @Autowired by Spring");
assertEquals("Dilbert", this.dilbert.getName(), "Person's name");
assertEquals(2, this.people.size(), "Number of people in context");
assertNotNull(this.dog, "Dogbert should have been @Autowired by Spring");
assertEquals("Dogbert", this.dog.getName(), "Dog's name");
assertNotNull(this.cat, "Catbert should have been @Autowired by Spring as the @Primary cat");
assertEquals("Catbert", this.cat.getName(), "Primary cat's name");
assertEquals(2, this.cats.size(), "Number of cats in context");
assertNotNull(this.enigma, "Enigma should have been injected via @Value by Spring");
assertEquals(new Integer(42), this.enigma, "enigma");
}
@Test
void autowiredParameterByTypeForSingleBean(@Autowired Dog dog) {
assertNotNull(dog, "Dogbert should have been @Autowired by Spring");
assertEquals("Dogbert", dog.getName(), "Dog's name");
}
@Test
void autowiredParameterByTypeForPrimaryBean(@Autowired Cat primaryCat) {
assertNotNull(primaryCat, "Primary cat should have been @Autowired by Spring");
assertEquals("Catbert", primaryCat.getName(), "Primary cat's name");
}
@Test
void autowiredParameterWithExplicitQualifier(@Qualifier("wally") Person person) {
assertNotNull(person, "Wally should have been @Autowired by Spring");
assertEquals("Wally", person.getName(), "Person's name");
}
/**
* NOTE: Test code must be compiled with "-g" (debug symbols) or "-parameters" in order
* for the parameter name to be used as the qualifier; otherwise, use
* {@code @Qualifier("wally")}.
*/
@Test
void autowiredParameterWithImplicitQualifierBasedOnParameterName(@Autowired Person wally) {
assertNotNull(wally, "Wally should have been @Autowired by Spring");
assertEquals("Wally", wally.getName(), "Person's name");
}
@Test
void autowiredParameterAsJavaUtilOptional(@Autowired Optional<Dog> dog) {
assertNotNull(dog, "Optional dog should have been @Autowired by Spring");
assertTrue(dog.isPresent(), "Value of Optional should be 'present'");
assertEquals("Dogbert", dog.get().getName(), "Dog's name");
}
@Test
void autowiredParameterThatDoesNotExistAsJavaUtilOptional(@Autowired Optional<Number> number) {
assertNotNull(number, "Optional number should have been @Autowired by Spring");
assertFalse(number.isPresent(), "Value of Optional number should not be 'present'");
}
@Test
void autowiredParameterThatDoesNotExistButIsNotRequired(@Autowired(required = false) Number number) {
assertNull(number, "Non-required number should have been @Autowired as 'null' by Spring");
}
@Test
void autowiredParameterOfList(@Autowired List<Person> peopleParam) {
assertNotNull(peopleParam, "list of people should have been @Autowired by Spring");
assertEquals(2, peopleParam.size(), "Number of people in context");
}
@Test
void valueParameterWithPrimitiveType(@Value("99") int num) {
assertEquals(99, num);
}
@Test
void valueParameterFromPropertyPlaceholder(@Value("${enigma}") Integer enigmaParam) {
assertNotNull(enigmaParam, "Enigma should have been injected via @Value by Spring");
assertEquals(new Integer(42), enigmaParam, "enigma");
}
@Test
void valueParameterFromDefaultValueForPropertyPlaceholder(@Value("${bogus:false}") Boolean defaultValue) {
assertNotNull(defaultValue, "Default value should have been injected via @Value by Spring");
assertEquals(false, defaultValue, "default value");
}
@Test
void valueParameterFromSpelExpression(@Value("#{@dilbert.name}") String name) {
assertNotNull(name, "Dilbert's name should have been injected via SpEL expression in @Value by Spring");
assertEquals("Dilbert", name, "name from SpEL expression");
}
@Test
void valueParameterFromSpelExpressionWithNestedPropertyPlaceholder(@Value("#{'Hello ' + ${enigma}}") String hello) {
assertNotNull(hello, "hello should have been injected via SpEL expression in @Value by Spring");
assertEquals("Hello 42", hello, "hello from SpEL expression");
}
@Test
void junitAndSpringMethodInjectionCombined(@Autowired Cat kittyCat, TestInfo testInfo, ApplicationContext context,
TestReporter testReporter) {
assertNotNull(testInfo, "TestInfo should have been injected by JUnit");
assertNotNull(testReporter, "TestReporter should have been injected by JUnit");
assertNotNull(context, "ApplicationContext should have been injected by Spring");
assertNotNull(kittyCat, "Cat should have been @Autowired by Spring");
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.SpringJUnitJupiterTestSuite;
import org.springframework.test.context.junit.jupiter.comics.Dog;
import org.springframework.test.context.junit.jupiter.comics.Person;
import static org.junit.jupiter.api.Assertions.*;
/**
* Integration tests which demonstrate support for {@link Autowired @Autowired}
* test class constructors with the Spring TestContext Framework and JUnit 5.
*
* <p>To run these tests in an IDE, simply run {@link SpringJUnitJupiterTestSuite}
* as a JUnit 4 test.
*
* @author Sam Brannen
* @since 5.0
* @see SpringExtension
* @see SpringJUnit5ConstructorInjectionTestCase
*/
@SpringJUnitConfig(TestConfig.class)
@TestPropertySource(properties = "enigma = 42")
class SpringJUnit5AutowiredConstructorInjectionTestCase {
final ApplicationContext applicationContext;
final Person dilbert;
final Dog dog;
final Integer enigma;
@Autowired
SpringJUnit5AutowiredConstructorInjectionTestCase(ApplicationContext applicationContext, Person dilbert, Dog dog,
@Value("${enigma}") Integer enigma) {
this.applicationContext = applicationContext;
this.dilbert = dilbert;
this.dog = dog;
this.enigma = enigma;
}
@Test
void applicationContextInjected() {
assertNotNull(applicationContext, "ApplicationContext should have been injected by Spring");
assertEquals(this.dilbert, applicationContext.getBean("dilbert", Person.class));
}
@Test
void beansInjected() {
assertNotNull(this.dilbert, "Dilbert should have been @Autowired by Spring");
assertEquals("Dilbert", this.dilbert.getName(), "Person's name");
assertNotNull(this.dog, "Dogbert should have been @Autowired by Spring");
assertEquals("Dogbert", this.dog.getName(), "Dog's name");
}
@Test
void propertyPlaceholderInjected() {
assertNotNull(this.enigma, "Enigma should have been injected via @Value by Spring");
assertEquals(new Integer(42), this.enigma, "enigma");
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.ApplicationContext;
import org.springframework.test.context.TestPropertySource;
import org.springframework.test.context.junit.SpringJUnitJupiterTestSuite;
import org.springframework.test.context.junit.jupiter.comics.Dog;
import org.springframework.test.context.junit.jupiter.comics.Person;
import static org.junit.jupiter.api.Assertions.*;
/**
* Integration tests which demonstrate support for autowiring individual
* parameters in test class constructors using {@link Autowired @Autowired}
* and {@link Value @Value} with the Spring TestContext Framework and JUnit 5.
*
* <p>To run these tests in an IDE, simply run {@link SpringJUnitJupiterTestSuite}
* as a JUnit 4 test.
*
* @author Sam Brannen
* @since 5.0
* @see SpringExtension
* @see SpringJUnit5AutowiredConstructorInjectionTestCase
*/
@SpringJUnitConfig(TestConfig.class)
@TestPropertySource(properties = "enigma = 42")
class SpringJUnit5ConstructorInjectionTestCase {
final ApplicationContext applicationContext;
final Person dilbert;
final Dog dog;
final Integer enigma;
final TestInfo testInfo;
SpringJUnit5ConstructorInjectionTestCase(ApplicationContext applicationContext, @Autowired Person dilbert,
@Autowired Dog dog, @Value("${enigma}") Integer enigma, TestInfo testInfo) {
this.applicationContext = applicationContext;
this.dilbert = dilbert;
this.dog = dog;
this.enigma = enigma;
this.testInfo = testInfo;
}
@Test
void applicationContextInjected() {
assertNotNull(applicationContext, "ApplicationContext should have been injected by Spring");
assertEquals(this.dilbert, applicationContext.getBean("dilbert", Person.class));
}
@Test
void beansInjected() {
assertNotNull(this.dilbert, "Dilbert should have been @Autowired by Spring");
assertEquals("Dilbert", this.dilbert.getName(), "Person's name");
assertNotNull(this.dog, "Dogbert should have been @Autowired by Spring");
assertEquals("Dogbert", this.dog.getName(), "Dog's name");
}
@Test
void propertyPlaceholderInjected() {
assertNotNull(this.enigma, "Enigma should have been injected via @Value by Spring");
assertEquals(new Integer(42), this.enigma, "enigma");
}
@Test
void testInfoInjected() {
assertNotNull(this.testInfo, "TestInfo should have been injected by JUnit");
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.context.support.PropertySourcesPlaceholderConfigurer;
import org.springframework.test.context.junit.jupiter.comics.Cat;
import org.springframework.test.context.junit.jupiter.comics.Dog;
import org.springframework.test.context.junit.jupiter.comics.Person;
/**
* Demo config for tests.
*
* @author Sam Brannen
* @since 5.0
*/
@Configuration
public class TestConfig {
@Bean
static PropertySourcesPlaceholderConfigurer placeholderConfigurer() {
return new PropertySourcesPlaceholderConfigurer();
}
@Bean
Person dilbert() {
return new Person("Dilbert");
}
@Bean
Person wally() {
return new Person("Wally");
}
@Bean
Dog dogbert() {
return new Dog("Dogbert");
}
@Primary
@Bean
Cat catbert() {
return new Cat("Catbert");
}
@Bean
Cat garfield() {
return new Cat("Garfield");
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.comics;
/**
* Demo class for tests.
*
* @author Sam Brannen
* @since 5.0
*/
public class Cat extends Character {
public Cat(String name) {
super(name);
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.comics;
/**
* Demo class for tests.
*
* @author Sam Brannen
* @since 5.0
*/
public abstract class Character {
private final String name;
Character(String name) {
this.name = name;
}
public String getName() {
return this.name;
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.comics;
/**
* Demo class for tests.
*
* @author Sam Brannen
* @since 5.0
*/
public class Dog extends Character {
public Dog(String name) {
super(name);
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.comics;
/**
* Demo class for tests.
*
* @author Sam Brannen
* @since 5.0
*/
public class Person extends Character {
public Person(String name) {
super(name);
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.defaultmethods;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.comics.Cat;
/**
* Parameterized test class for integration tests that demonstrate support for
* interface default methods and Java generics in JUnit 5 test classes when used
* with the Spring TestContext Framework and the {@link SpringExtension}.
*
* @author Sam Brannen
* @since 5.0
*/
class CatInterfaceDefaultMethodsTestCase implements GenericComicCharactersInterfaceDefaultMethodsTestCase<Cat> {
@Override
public int getExpectedNumCharacters() {
return 2;
}
@Override
public String getExpectedName() {
return "Catbert";
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.defaultmethods;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.comics.Dog;
/**
* Parameterized test class for integration tests that demonstrate support for
* interface default methods and Java generics in JUnit 5 test classes when used
* with the Spring TestContext Framework and the {@link SpringExtension}.
*
* @author Sam Brannen
* @since 5.0
*/
class DogInterfaceDefaultMethodsTestCase implements GenericComicCharactersInterfaceDefaultMethodsTestCase<Dog> {
@Override
public int getExpectedNumCharacters() {
return 1;
}
@Override
public String getExpectedName() {
return "Dogbert";
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.defaultmethods;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.SpringJUnitConfig;
import org.springframework.test.context.junit.jupiter.TestConfig;
import org.springframework.test.context.junit.jupiter.comics.Character;
import static org.junit.jupiter.api.Assertions.*;
/**
* Interface for integration tests that demonstrate support for interface default
* methods and Java generics in JUnit Jupiter test classes when used with the Spring
* TestContext Framework and the {@link SpringExtension}.
*
* @author Sam Brannen
* @since 5.0
*/
@SpringJUnitConfig(TestConfig.class)
interface GenericComicCharactersInterfaceDefaultMethodsTestCase<C extends Character> {
@Test
default void autowiredParameterWithParameterizedList(@Autowired List<C> characters) {
assertEquals(getExpectedNumCharacters(), characters.size(), "Number of characters in context");
}
@Test
default void autowiredParameterWithGenericBean(@Autowired C character) {
assertNotNull(character, "Character should have been @Autowired by Spring");
assertEquals(getExpectedName(), character.getName(), "character's name");
}
int getExpectedNumCharacters();
String getExpectedName();
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.generics;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.comics.Cat;
/**
* Parameterized test class for integration tests that demonstrate support for
* Java generics in JUnit 5 test classes when used with the Spring TestContext
* Framework and the {@link SpringExtension}.
*
* @author Sam Brannen
* @since 5.0
*/
class CatTestCase extends GenericComicCharactersTestCase<Cat> {
@Override
int getExpectedNumCharacters() {
return 2;
}
@Override
String getExpectedName() {
return "Catbert";
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.generics;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.comics.Dog;
/**
* Parameterized test class for integration tests that demonstrate support for
* Java generics in JUnit 5 test classes when used with the Spring TestContext
* Framework and the {@link SpringExtension}.
*
* @author Sam Brannen
* @since 5.0
*/
class DogTestCase extends GenericComicCharactersTestCase<Dog> {
@Override
int getExpectedNumCharacters() {
return 1;
}
@Override
String getExpectedName() {
return "Dogbert";
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.generics;
import java.util.List;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.context.junit.jupiter.TestConfig;
import org.springframework.test.context.junit.jupiter.comics.Character;
import static org.junit.jupiter.api.Assertions.*;
/**
* Abstract base class for integration tests that demonstrate support for
* Java generics in JUnit 5 test classes when used with the Spring TestContext
* Framework and the {@link SpringExtension}.
*
* @author Sam Brannen
* @since 5.0
*/
@ExtendWith(SpringExtension.class)
@ContextConfiguration(classes = TestConfig.class)
abstract class GenericComicCharactersTestCase<T extends Character> {
@Autowired
T character;
@Autowired
List<T> characters;
@Test
void autowiredFields() {
assertNotNull(this.character, "Character should have been @Autowired by Spring");
assertEquals(getExpectedName(), character.getName(), "character's name");
assertEquals(getExpectedNumCharacters(), this.characters.size(), "Number of characters in context");
}
@Test
void autowiredParameterByTypeForSingleGenericBean(@Autowired T character) {
assertNotNull(character, "Character should have been @Autowired by Spring");
assertEquals(getExpectedName(), character.getName(), "character's name");
}
abstract int getExpectedNumCharacters();
abstract String getExpectedName();
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.web;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.SpringJUnitJupiterTestSuite;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import static org.hamcrest.CoreMatchers.*;
import static org.springframework.http.MediaType.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
/**
* Integration tests which demonstrate how to set up a {@link MockMvc}
* instance in an {@link BeforeEach @BeforeEach} method with the
* {@link SpringExtension} (registered via a custom
* {@link SpringJUnitWebConfig @SpringJUnitWebConfig} composed annotation).
*
* <p>To run these tests in an IDE, simply run {@link SpringJUnitJupiterTestSuite}
* as a JUnit 4 test.
*
* @author Sam Brannen
* @since 5.0
* @see SpringExtension
* @see SpringJUnitWebConfig
* @see org.springframework.test.context.junit.jupiter.web.WebSpringExtensionTestCase
*/
@SpringJUnitWebConfig(WebConfig.class)
class MultipleWebRequestsSpringExtensionTestCase {
MockMvc mockMvc;
@BeforeEach
void setUpMockMvc(WebApplicationContext wac) {
this.mockMvc = webAppContextSetup(wac)
.alwaysExpect(status().isOk())
.alwaysExpect(content().contentTypeCompatibleWith(APPLICATION_JSON))
.build();
}
@Test
void getPerson42() throws Exception {
this.mockMvc.perform(get("/person/42").accept(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.name", is("Dilbert")));
}
@Test
void getPerson99() throws Exception {
this.mockMvc.perform(get("/person/99").accept(MediaType.APPLICATION_JSON))
.andExpect(jsonPath("$.name", is("Wally")));
}
}
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.web;
import org.springframework.test.context.junit.jupiter.comics.Person;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
/**
* @author Sam Brannen
* @since 5.0
*/
@RestController
class PersonController {
@GetMapping("/person/{id}")
Person getPerson(@PathVariable long id) {
if (id == 42) {
return new Person("Dilbert");
}
return new Person("Wally");
}
}
\ No newline at end of file
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.web;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.servlet.config.annotation.EnableWebMvc;
/**
* @author Sam Brannen
* @since 5.0
*/
@Configuration
@EnableWebMvc
class WebConfig {
@Bean
PersonController personController() {
return new PersonController();
}
}
\ No newline at end of file
/*
* Copyright 2002-2016 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
*
* http://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.junit.jupiter.web;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit.SpringJUnitJupiterTestSuite;
import org.springframework.test.context.junit.jupiter.SpringExtension;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.web.context.WebApplicationContext;
import static org.hamcrest.CoreMatchers.*;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*;
import static org.springframework.test.web.servlet.setup.MockMvcBuilders.*;
/**
* Integration tests which demonstrate use of the Spring MVC Test Framework and
* the Spring TestContext Framework with JUnit Jupiter and the
* {@link SpringExtension} (via a custom
* {@link SpringJUnitWebConfig @SpringJUnitWebConfig} composed annotation).
*
* <p>Note how the {@link #springMvcTest(WebApplicationContext)} test method
* has the {@link WebApplicationContext} injected as a method parameter.
* This allows the {@link MockMvc} instance to be configured local to the
* test method without any fields in the test class.
*
* <p>To run these tests in an IDE, simply run {@link SpringJUnitJupiterTestSuite}
* as a JUnit 4 test.
*
* @author Sam Brannen
* @since 5.0
* @see SpringExtension
* @see SpringJUnitWebConfig
* @see org.springframework.test.context.junit.jupiter.web.MultipleWebRequestsSpringExtensionTestCase
* @see org.springframework.test.context.junit.jupiter.SpringExtensionTests
* @see org.springframework.test.context.junit.jupiter.ComposedSpringExtensionTests
*/
@SpringJUnitWebConfig(WebConfig.class)
@DisplayName("Web SpringExtension Tests")
class WebSpringExtensionTestCase {
@Test
void springMvcTest(WebApplicationContext wac) throws Exception {
webAppContextSetup(wac).build()
.perform(get("/person/42").accept(MediaType.APPLICATION_JSON))
.andExpect(status().isOk())
.andExpect(jsonPath("$.name", is("Dilbert")));
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册