Add support for ApplicationContextRunner in ProjectAssetTester

Closes gh-1004
This commit is contained in:
Stephane Nicoll
2019-09-17 09:01:57 +02:00
parent 1d213258a2
commit 23cc192813
10 changed files with 111 additions and 72 deletions

View File

@@ -33,12 +33,20 @@ import io.spring.initializr.generator.project.ProjectDirectoryFactory;
import io.spring.initializr.generator.project.ProjectGenerationContext;
import io.spring.initializr.generator.project.contributor.ProjectContributor;
import org.springframework.boot.test.context.assertj.AssertableApplicationContext;
import org.springframework.boot.test.context.runner.ApplicationContextRunner;
import org.springframework.boot.test.context.runner.ContextConsumer;
/**
* A tester for project asset that does not detect available {@link ProjectContributor
* contributors} and does not register any bean to the context. Contributors can be added
* using a {@link #withConfiguration(Class[]) configuration class} or a
* {@link #withContextInitializer(Consumer) customization of the project generation
* context}.
* <p>
* Alternatively, the context can be queried the same way {@link ApplicationContextRunner}
* works by {@link #configure(MutableProjectDescription, ContextConsumer) configuring} the
* context.
*
* @author Stephane Nicoll
*/
@@ -70,6 +78,25 @@ public class ProjectAssetTester extends AbstractProjectGenerationTester<ProjectA
return withContextInitializer((context) -> context.register(configurationClasses));
}
/**
* Configure a {@link ProjectGenerationContext} using the specified
* {@code description} and use the {@link ContextConsumer} to assert the context.
* @param description the description of the project to configure
* @param consumer the consumer of the created {@link ProjectGenerationContext}
* @see ApplicationContextRunner#run(ContextConsumer)
*/
public void configure(MutableProjectDescription description,
ContextConsumer<AssertableApplicationContext> consumer) {
invokeProjectGeneration(description, (contextInitializer) -> {
new ApplicationContextRunner(ProjectGenerationContext::new).withInitializer((ctx) -> {
ProjectGenerationContext projectGenerationContext = (ProjectGenerationContext) ctx;
projectGenerationContext.registerBean(ProjectDescription.class, () -> description);
contextInitializer.accept(projectGenerationContext);
}).run(consumer);
return null;
});
}
/**
* Generate a project asset using the specified {@link ProjectAssetGenerator}.
* @param description the description of the project to generate

View File

@@ -18,18 +18,21 @@ package io.spring.initializr.generator.test.project;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Map;
import io.spring.initializr.generator.io.IndentingWriterFactory;
import io.spring.initializr.generator.io.template.MustacheTemplateRenderer;
import io.spring.initializr.generator.project.MutableProjectDescription;
import io.spring.initializr.generator.project.ProjectDescription;
import io.spring.initializr.generator.project.contributor.ProjectContributor;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import org.springframework.beans.factory.UnsatisfiedDependencyException;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
/**
* Tests for {@link ProjectAssetTester}.
@@ -40,30 +43,48 @@ class ProjectAssetTesterTests {
@Test
void testerHasNoRegisteredIndentingWriterFactoryByDefault() {
Map<String, IndentingWriterFactory> contributors = new ProjectAssetTester().generate(
new MutableProjectDescription(), (context) -> context.getBeansOfType(IndentingWriterFactory.class));
assertThat(contributors).isEmpty();
new ProjectAssetTester().configure(new MutableProjectDescription(),
(context) -> assertThat(context).doesNotHaveBean(IndentingWriterFactory.class));
}
@Test
void testerWithIndentingWriterFactory() {
new ProjectAssetTester().withIndentingWriterFactory().generate(new MutableProjectDescription(),
(context) -> assertThat(context.getBeansOfType(IndentingWriterFactory.class)).hasSize(1));
new ProjectAssetTester().withIndentingWriterFactory().configure(new MutableProjectDescription(),
(context) -> assertThat(context).hasSingleBean(IndentingWriterFactory.class));
}
@Test
void testerWithExplicitProjectContributors(@TempDir Path directory) {
MutableProjectDescription description = new MutableProjectDescription();
description.setName("test.text");
ProjectStructure project = new ProjectAssetTester().withDirectory(directory)
.withConfiguration(ContributorsConfiguration.class).generate(new MutableProjectDescription());
.withConfiguration(ContributorsConfiguration.class).generate(description);
assertThat(project).filePaths().containsOnly("test.text", "test2.text");
}
@Test
void testerWithContextFailureIsProperlyReported() {
new ProjectAssetTester().withConfiguration(ContributorFailureConfiguration.class)
.configure(new MutableProjectDescription(), (context) -> {
assertThat(context).hasFailed();
assertThat(context.getStartupFailure()).isInstanceOf(UnsatisfiedDependencyException.class);
assertThat(context.getStartupFailure().getMessage()).doesNotContain("Should not be invoked");
});
}
@Test
void testerWithContextSuccessFailToAssertFailure() {
assertThatExceptionOfType(AssertionError.class)
.isThrownBy(() -> new ProjectAssetTester().withConfiguration(ContributorsConfiguration.class)
.configure(new MutableProjectDescription(), (context) -> assertThat(context).hasFailed()));
}
@Configuration
static class ContributorsConfiguration {
@Bean
ProjectContributor contributor1() {
return (projectDirectory) -> Files.createFile(projectDirectory.resolve("test.text"));
ProjectContributor contributor1(ProjectDescription description) {
return (projectDirectory) -> Files.createFile(projectDirectory.resolve(description.getName()));
}
@Bean
@@ -73,4 +94,14 @@ class ProjectAssetTesterTests {
}
@Configuration
static class ContributorFailureConfiguration {
@Bean
ProjectContributor failContributor(MustacheTemplateRenderer templateRenderer) {
throw new IllegalStateException("Should not be invoked");
}
}
}