Provide idiomatic test setup when JUnit Jupiter is available

This commit provides a better test infrastructure when JUnit 5 is
available:

* The default test class uses JUnit Jupiter API
* The vintage engine that the Spring Boot starter provides is excluded
so that only the Junit Jupiter API is available on the classpath

Closes gh-905
This commit is contained in:
Stephane Nicoll 2019-05-21 14:44:20 +02:00
parent a2950c9a56
commit 7a30f771f2
9 changed files with 153 additions and 25 deletions

View File

@ -17,12 +17,14 @@
package io.spring.initializr.generator.spring.build;
import io.spring.initializr.generator.buildsystem.Build;
import io.spring.initializr.generator.buildsystem.Dependency.Exclusion;
import io.spring.initializr.generator.buildsystem.DependencyScope;
import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem;
import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem;
import io.spring.initializr.generator.condition.ConditionalOnBuildSystem;
import io.spring.initializr.generator.condition.ConditionalOnLanguage;
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
import io.spring.initializr.generator.condition.ConditionalOnPlatformVersion;
import io.spring.initializr.generator.language.kotlin.KotlinLanguage;
import io.spring.initializr.generator.packaging.war.WarPackaging;
import io.spring.initializr.generator.project.ProjectGenerationConfiguration;
@ -45,11 +47,21 @@ import org.springframework.context.annotation.Bean;
public class BuildProjectGenerationConfiguration {
@Bean
public BuildCustomizer<Build> testStarterContributor() {
@ConditionalOnPlatformVersion("[1.5.0.RELEASE,2.2.0.M3)")
public BuildCustomizer<Build> junit4TestStarterContributor() {
return (build) -> build.dependencies().add("test", "org.springframework.boot",
"spring-boot-starter-test", DependencyScope.TEST_COMPILE);
}
@Bean
@ConditionalOnPlatformVersion("2.2.0.M3")
public BuildCustomizer<Build> junitJupiterTestStarterContributor() {
return (build) -> build.dependencies().add("test", "org.springframework.boot",
"spring-boot-starter-test", null, DependencyScope.TEST_COMPILE, null,
new Exclusion("org.junit.vintage", "junit-vintage-engine"),
new Exclusion("junit", "junit"));
}
@Bean
public DefaultStarterBuildCustomizer defaultStarterContributor(
InitializrMetadata metadata) {

View File

@ -43,7 +43,8 @@ public class SourceCodeProjectGenerationConfiguration {
}
@Bean
public TestApplicationTypeCustomizer<TypeDeclaration> springBootTestAnnotator() {
@ConditionalOnPlatformVersion("[1.5.0.RELEASE,2.2.0.M3)")
public TestApplicationTypeCustomizer<TypeDeclaration> junit4SpringBootTestTypeCustomizer() {
return (typeDeclaration) -> {
typeDeclaration.annotate(Annotation.name("org.junit.runner.RunWith",
(annotation) -> annotation.attribute("value", Class.class,
@ -53,6 +54,13 @@ public class SourceCodeProjectGenerationConfiguration {
};
}
@Bean
@ConditionalOnPlatformVersion("2.2.0.M3")
public TestApplicationTypeCustomizer<TypeDeclaration> junitJupiterSpringBootTestTypeCustomizer() {
return (typeDeclaration) -> typeDeclaration.annotate(
Annotation.name("org.springframework.boot.test.context.SpringBootTest"));
}
/**
* Language-agnostic source code contributions for projects using war packaging.
*/

View File

@ -23,6 +23,7 @@ import io.spring.initializr.generator.buildsystem.gradle.GradleBuildSystem;
import io.spring.initializr.generator.buildsystem.maven.MavenBuildSystem;
import io.spring.initializr.generator.condition.ConditionalOnBuildSystem;
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
import io.spring.initializr.generator.condition.ConditionalOnPlatformVersion;
import io.spring.initializr.generator.language.Annotation;
import io.spring.initializr.generator.language.Parameter;
import io.spring.initializr.generator.language.groovy.GroovyExpressionStatement;
@ -61,7 +62,8 @@ class GroovyProjectGenerationDefaultContributorsConfiguration {
}
@Bean
public TestApplicationTypeCustomizer<GroovyTypeDeclaration> testMethodContributor() {
@ConditionalOnPlatformVersion("[1.5.0.RELEASE,2.2.0.M3)")
public TestApplicationTypeCustomizer<GroovyTypeDeclaration> junit4TestMethodContributor() {
return (typeDeclaration) -> {
GroovyMethodDeclaration method = GroovyMethodDeclaration
.method("contextLoads").modifiers(Modifier.PUBLIC).returning("void")
@ -71,6 +73,17 @@ class GroovyProjectGenerationDefaultContributorsConfiguration {
};
}
@Bean
@ConditionalOnPlatformVersion("2.2.0.M3")
public TestApplicationTypeCustomizer<GroovyTypeDeclaration> junitJupiterTestMethodContributor() {
return (typeDeclaration) -> {
GroovyMethodDeclaration method = GroovyMethodDeclaration
.method("contextLoads").returning("void").body();
method.annotate(Annotation.name("org.junit.jupiter.api.Test"));
typeDeclaration.addMethodDeclaration(method);
};
}
@Bean
public BuildCustomizer<Build> groovyDependenciesConfigurer() {
return new GroovyDependenciesConfigurer();

View File

@ -19,6 +19,7 @@ package io.spring.initializr.generator.spring.code.java;
import java.lang.reflect.Modifier;
import io.spring.initializr.generator.condition.ConditionalOnPackaging;
import io.spring.initializr.generator.condition.ConditionalOnPlatformVersion;
import io.spring.initializr.generator.language.Annotation;
import io.spring.initializr.generator.language.Parameter;
import io.spring.initializr.generator.language.java.JavaExpressionStatement;
@ -58,7 +59,8 @@ class JavaProjectGenerationDefaultContributorsConfiguration {
}
@Bean
public TestApplicationTypeCustomizer<JavaTypeDeclaration> testMethodContributor() {
@ConditionalOnPlatformVersion("[1.5.0.RELEASE,2.2.0.M3)")
public TestApplicationTypeCustomizer<JavaTypeDeclaration> junit4TestMethodContributor() {
return (typeDeclaration) -> {
typeDeclaration.modifiers(Modifier.PUBLIC);
JavaMethodDeclaration method = JavaMethodDeclaration.method("contextLoads")
@ -68,6 +70,17 @@ class JavaProjectGenerationDefaultContributorsConfiguration {
};
}
@Bean
@ConditionalOnPlatformVersion("2.2.0.M3")
public TestApplicationTypeCustomizer<JavaTypeDeclaration> junitJupiterTestMethodContributor() {
return (typeDeclaration) -> {
JavaMethodDeclaration method = JavaMethodDeclaration.method("contextLoads")
.returning("void").body();
method.annotate(Annotation.name("org.junit.jupiter.api.Test"));
typeDeclaration.addMethodDeclaration(method);
};
}
/**
* Java source code contributions for projects using war packaging.
*/

View File

@ -53,7 +53,8 @@ import org.springframework.context.annotation.Configuration;
class KotlinProjectGenerationDefaultContributorsConfiguration {
@Bean
public TestApplicationTypeCustomizer<KotlinTypeDeclaration> testMethodContributor() {
@ConditionalOnPlatformVersion("[1.5.0.RELEASE,2.2.0.M3)")
public TestApplicationTypeCustomizer<KotlinTypeDeclaration> junit4TestMethodContributor() {
return (typeDeclaration) -> {
KotlinFunctionDeclaration function = KotlinFunctionDeclaration
.function("contextLoads").body();
@ -62,6 +63,17 @@ class KotlinProjectGenerationDefaultContributorsConfiguration {
};
}
@Bean
@ConditionalOnPlatformVersion("2.2.0.M3")
public TestApplicationTypeCustomizer<KotlinTypeDeclaration> junitJupiterTestMethodContributor() {
return (typeDeclaration) -> {
KotlinFunctionDeclaration function = KotlinFunctionDeclaration
.function("contextLoads").body();
function.annotate(Annotation.name("org.junit.jupiter.api.Test"));
typeDeclaration.addFunctionDeclaration(function);
};
}
@Bean
public BuildCustomizer<Build> kotlinDependenciesConfigurer(
ResolvedProjectDescription projectDescription) {

View File

@ -58,16 +58,8 @@ class SourceCodeProjectGenerationConfigurationTests {
}
@Test
@SuppressWarnings("unchecked")
void addsACustomizerThatAppliesTestAnnotationsOnTestClass() {
TypeDeclaration declaration = this.projectTester
.generate(new ProjectDescription(), (context) -> {
TypeDeclaration type = new TypeDeclaration("Test");
TestApplicationTypeCustomizer<TypeDeclaration> bean = context
.getBean(TestApplicationTypeCustomizer.class);
bean.customize(type);
return type;
});
void addsACustomizerThatAppliesTestAnnotationsOnTestClassWithJunit4() {
TypeDeclaration declaration = generateTestTypeDeclaration("2.1.0.RELEASE");
assertThat(declaration.getAnnotations()).hasSize(2);
assertThat(declaration.getAnnotations().get(0).getName())
.isEqualTo("org.junit.runner.RunWith");
@ -77,6 +69,27 @@ class SourceCodeProjectGenerationConfigurationTests {
.isEqualTo("org.springframework.boot.test.context.SpringBootTest");
}
@Test
void addsACustomizerThatAppliesTestAnnotationsOnTestClassWithJunit5() {
TypeDeclaration declaration = generateTestTypeDeclaration("2.2.0.RELEASE");
assertThat(declaration.getAnnotations()).hasSize(1);
assertThat(declaration.getAnnotations().get(0).getName())
.isEqualTo("org.springframework.boot.test.context.SpringBootTest");
}
@SuppressWarnings("unchecked")
private TypeDeclaration generateTestTypeDeclaration(String version) {
ProjectDescription description = new ProjectDescription();
description.setPlatformVersion(Version.parse(version));
return this.projectTester.generate(description, (context) -> {
TypeDeclaration type = new TypeDeclaration("Test");
TestApplicationTypeCustomizer<TypeDeclaration> bean = context
.getBean(TestApplicationTypeCustomizer.class);
bean.customize(type);
return type;
});
}
@Test
void springBoot15WarServletInitializerContributor() {
runWarTest("1.5.0",

View File

@ -49,7 +49,9 @@ class GroovyProjectGenerationConfigurationTests {
GroovyProjectGenerationConfiguration.class)
.withDirectory(directory).withDescriptionCustomizer((description) -> {
description.setLanguage(new GroovyLanguage());
description.setPlatformVersion(Version.parse("2.1.0.RELEASE"));
if (description.getPlatformVersion() == null) {
description.setPlatformVersion(Version.parse("2.1.0.RELEASE"));
}
description.setBuildSystem(new MavenBuildSystem());
});
}
@ -63,9 +65,10 @@ class GroovyProjectGenerationConfigurationTests {
}
@Test
void testClassIsContributed() {
ProjectStructure projectStructure = this.projectTester
.generate(new ProjectDescription());
void testClassIsContributedWithJUnit4() {
ProjectDescription description = new ProjectDescription();
description.setPlatformVersion(Version.parse("2.1.4.RELEASE"));
ProjectStructure projectStructure = this.projectTester.generate(description);
assertThat(projectStructure.getRelativePathsOfProjectFiles())
.contains("src/test/groovy/com/example/demo/DemoApplicationTests.groovy");
List<String> lines = projectStructure.readAllLines(
@ -79,6 +82,22 @@ class GroovyProjectGenerationConfigurationTests {
" void contextLoads() {", " }", "", "}");
}
@Test
void testClassIsContributedWithJUnit5() {
ProjectDescription description = new ProjectDescription();
description.setPlatformVersion(Version.parse("2.2.0.RELEASE"));
ProjectStructure projectStructure = this.projectTester.generate(description);
assertThat(projectStructure.getRelativePathsOfProjectFiles())
.contains("src/test/groovy/com/example/demo/DemoApplicationTests.groovy");
List<String> lines = projectStructure.readAllLines(
"src/test/groovy/com/example/demo/DemoApplicationTests.groovy");
assertThat(lines).containsExactly("package com.example.demo", "",
"import org.junit.jupiter.api.Test",
"import org.springframework.boot.test.context.SpringBootTest", "",
"@SpringBootTest", "class DemoApplicationTests {", "", " @Test",
" void contextLoads() {", " }", "", "}");
}
@Test
void servletInitializerIsContributedWhenGeneratingProjectThatUsesWarPackaging() {
ProjectDescription description = new ProjectDescription();

View File

@ -49,7 +49,9 @@ class JavaProjectGenerationConfigurationTests {
JavaProjectGenerationConfiguration.class)
.withDirectory(directory).withDescriptionCustomizer((description) -> {
description.setLanguage(new JavaLanguage());
description.setPlatformVersion(Version.parse("2.1.0.RELEASE"));
if (description.getPlatformVersion() == null) {
description.setPlatformVersion(Version.parse("2.1.0.RELEASE"));
}
description.setBuildSystem(new MavenBuildSystem());
});
}
@ -63,8 +65,9 @@ class JavaProjectGenerationConfigurationTests {
}
@Test
void testClassIsContributed() {
void testClassIsContributedWithJUnit4() {
ProjectDescription description = new ProjectDescription();
description.setPlatformVersion(Version.parse("2.1.4.RELEASE"));
ProjectStructure projectStructure = this.projectTester.generate(description);
assertThat(projectStructure.getRelativePathsOfProjectFiles())
.contains("src/test/java/com/example/demo/DemoApplicationTests.java");
@ -79,6 +82,22 @@ class JavaProjectGenerationConfigurationTests {
" public void contextLoads() {", " }", "", "}");
}
@Test
void testClassIsContributedWithJUnit5() {
ProjectDescription description = new ProjectDescription();
description.setPlatformVersion(Version.parse("2.2.0.RELEASE"));
ProjectStructure projectStructure = this.projectTester.generate(description);
assertThat(projectStructure.getRelativePathsOfProjectFiles())
.contains("src/test/java/com/example/demo/DemoApplicationTests.java");
List<String> lines = projectStructure
.readAllLines("src/test/java/com/example/demo/DemoApplicationTests.java");
assertThat(lines).containsExactly("package com.example.demo;", "",
"import org.junit.jupiter.api.Test;",
"import org.springframework.boot.test.context.SpringBootTest;", "",
"@SpringBootTest", "class DemoApplicationTests {", "", " @Test",
" void contextLoads() {", " }", "", "}");
}
@Test
void servletInitializerIsContributedWhenGeneratingProjectThatUsesWarPackaging() {
ProjectDescription description = new ProjectDescription();

View File

@ -52,7 +52,9 @@ class KotlinProjectGenerationConfigurationTests {
() -> new SimpleKotlinProjectSettings("1.2.70"))
.withDescriptionCustomizer((description) -> {
description.setLanguage(new KotlinLanguage());
description.setPlatformVersion(Version.parse("2.1.0.RELEASE"));
if (description.getPlatformVersion() == null) {
description.setPlatformVersion(Version.parse("2.1.0.RELEASE"));
}
description.setBuildSystem(new MavenBuildSystem());
});
}
@ -66,9 +68,10 @@ class KotlinProjectGenerationConfigurationTests {
}
@Test
void testClassIsContributed() {
ProjectStructure projectStructure = this.projectTester
.generate(new ProjectDescription());
void testClassIsContributedWithJunit4() {
ProjectDescription description = new ProjectDescription();
description.setPlatformVersion(Version.parse("2.1.4.RELEASE"));
ProjectStructure projectStructure = this.projectTester.generate(description);
assertThat(projectStructure.getRelativePathsOfProjectFiles())
.contains("src/test/kotlin/com/example/demo/DemoApplicationTests.kt");
List<String> lines = projectStructure
@ -82,6 +85,22 @@ class KotlinProjectGenerationConfigurationTests {
" fun contextLoads() {", " }", "", "}");
}
@Test
void testClassIsContributedWithJunit5() {
ProjectDescription description = new ProjectDescription();
description.setPlatformVersion(Version.parse("2.2.0.RELEASE"));
ProjectStructure projectStructure = this.projectTester.generate(description);
assertThat(projectStructure.getRelativePathsOfProjectFiles())
.contains("src/test/kotlin/com/example/demo/DemoApplicationTests.kt");
List<String> lines = projectStructure
.readAllLines("src/test/kotlin/com/example/demo/DemoApplicationTests.kt");
assertThat(lines).containsExactly("package com.example.demo", "",
"import org.junit.jupiter.api.Test",
"import org.springframework.boot.test.context.SpringBootTest", "",
"@SpringBootTest", "class DemoApplicationTests {", "", " @Test",
" fun contextLoads() {", " }", "", "}");
}
@Test
void servletInitializerIsContributedWhenGeneratingProjectThatUsesWarPackaging() {
ProjectDescription description = new ProjectDescription();