Different classes exist to help writing tests for Recipe
s, Condition
s and Action
s.
Linebreaks, encoding and path separator do (most probably will) differ depending on the OS the tests and the application is executed on.
To make the tests and application run on Windows, Linux and OSX you must take precautions in some cases.
When testing Action
s and Condition
s you’ll need a initialized ProjectContext as test fixture.
To avoid reading projects for testing from the filesystem the TestProjectContext
can be used.
The TestProjectContext
offers ways to create all kinds of ProjectContext instances initialized from resorces given as
strings as if they were read from filesystem. Have a look at the API documentation for details.
-
Creates different pom.xml. A blank default, with given dependencies defined, from a given String or as Mockito mock
-
Provides a method to register additional ResourceWrapper for specialized resources
String sourceCode = "package com.acme.app;\npublic class MyClass {}";
ProjectContext projectContext = TestProjectContext.buildProjectContext() (1)
.withBuildFileHavingDependencies("org.junit.jupiter:junit-jupiter-api:5.7.0") (2)
.withJavaSources(sourceCode) (3)
.build(); (4)
// Use ProjectContext to test Action or Condition
-
Call TestProjectContext static builder method which will inject a mock for ApplicationEventPublisher
-
Add required dependencies to the classpath (assume they’re needed). This will add a pom.xml declaring the provided dependencies.
-
Add a new Java file with given source to
src/main/java/com/acme/app/MyClass.java
-
build and return the initialized ProjectContext.
If you want to create a ProjectContext from filesystem, ProjectContextFileSystemTestSupport
is your friend.
It assumes a directory testcode
in the same module as the test resides in.
The initial project is read from a given
directory inside testcode
, let’s say testcode/given/my-project
.
The resources are then copied to target/test-projects/my-project
and the ProjectContext is created from this directory.
@Test
void someTest() {
ProjectContext projectContext = ProjectContextFileSystemTestSupport
.createProjectContextFromDir("boot-23-app");
// modify ProjectContext
}
Copies all resources from ./testcode/given/boot-23-app
to ./target/test-projects/boot-23-app
and creates a ProjectContext from it.
If you want to integration test a recipe against a project read from filesystem, RecipeIntegrationTestSupport
can help you.
String applicationDir = "example-app"; (1)
RecipeIntegrationTestSupport.initializeProject(applicationDir)
.andApplyRecipe("boot-2.4-2.5-datasource-initializer"); (2)
Path javaClass = RecipeIntegrationTestSupport.getResultDir(applicationDir).resolve("src/main/java/com/example/SomeJavaClass.java"); (3)
assertThat(javaClass).hasContent("..."); (4)
-
Provide a project, here under
./testcode/example-app/given
. This project will be copied to a clean dirtarget/test-projects/example-app
-
Scan the copied project and apply the given recipe against it
-
Retrieve the path to a resource after migration
-
Verify the resource has expected content
For end-to-end tests using the shell commands IntegrationTestBaseClass
will be helpful.
These are the most complete tests but also the slowest.
Note
|
Currently these tests reside in spring-shell module.
|
public class MyFullBlownIntegrationTest extends IntegrationTestBaseClass {
@Override
protected String getTestSubDir() { (1)
return "some-dir/project-dir"; (2)
}
@Test
@Tag("integration")
void migrateSomethingToSpringBoot() {
initializeTestProject(); (3)
scanProject(); (4)
applyRecipe("initialize-spring-boot-migration"); (5)
applyRecipe("migrate-x-to-boot"); (6)
// simulate manual step
replaceFile( (7)
getTestDir().resolve("src/test/java/com/example/jee/app/PersonServiceTest.java"),
getTestDir().resolve("manual-step/BootifiedPersonServiceTest.java")
);
String localBusinessInterface = loadJavaFile("com.example.jee.app.ejb.local", "ABusinessInterface"); (8)
// verify @Local was removed
assertThat(localBusinessInterface).doesNotContain("@Local"); (9)
executeMavenGoals(getTestDir(), "clean", "package", "spring-boot:build-image"); (10)
int port = startDockerContainer("jee-app:8.0.5-SNAPSHOT", 8080); (11)
TestRestTemplate testRestTemplate = new TestRestTemplate(); (12)
// Test Servlet
String response = testRestTemplate.getForObject("http://localhost:" + port + "/HelloWorld", String.class); (13)
assertThat(response).isEqualTo("Hello World!"); (14)
}
}
-
The
getTestSubDir()
method must be implemented. -
It must return the path to the test project in
src/test/resources
-
Copies test project from
src/test/resources/some-dir/project-dir
totarget/sbm-integration-test/some-dir/project-dir
-
Scans the copied test project, same as calling
scan
in CLI -
Apply the recipe
initialize-spring-boot-migration
, same as callingapply initialize-spring-boot-migration
in CLI. Changes will be reflected in the filesystem after this call. -
Apply another recipe
migrate-x-to-boot
-
Replace a file, here because the Test needs to be migrated manually
-
Load the content a Java file as String
-
Assertions about the context of the Java file
-
Call
mvn clean package spring-boot:build-image
in the test project -
Start the docker image from the last step containing the migrated Spring application
-
Create a RestTemplate
-
Use the RestTemplate to retrive some data from the migrated Spring application running in Docker
-
Verify the response