I have a SpringBoot multimodule application, something like that:
core customer1 -> depends on core customer2 -> depends on core
I want to write integration tests for both, but I don't want to duplicate my core test code. Now I have an abstract class with SpringBootTest(classes = Customer1Application.class) and a lot of test classes, mostly testing the core functionality.
@ContextConfiguration
@SpringBootTest(classes = Customer1Application.class)
@AutoConfigureMockMvc
public abstract class AbstractSpringBootTest
{
@Autowired
protected MockMvc mockMvc;
@Autowired
protected Validator validator;
...
}
I want to check if the changes in Customer2 application break something in core functionality, so I want to run these tests with @SpringBootTest(classes = Customer2Application.class) annotation.
How is it possible to configure the application class in the annotation? Is there a way to run the tests with my other application context without manually changing the annotation or duplicating all the steps?
I don't know if it will work, but I would try removing @SpringBootTest
from AbstractSpringBootTest
and then defining two test classes as follows:
@SpringBootTest(classes = Customer1Application.class)
class Customer1ApplicationSpringBootTest extends AbstractSpringBootTest {}
@SpringBootTest(classes = Customer2Application.class)
class Customer2ApplicationSpringBootTest extends AbstractSpringBootTest {}
EDIT:
So I dug around Spring Boot sources and came up with this solution .
Essentially to be able to use system property or property file to configure which @SpringBootApplication is supposed to be tested you need to copy the source of class org.springframework.boot.test.context.SpringBootConfigurationFinder
to your own test source root and the edit method private Class<?> scanPackage(String source)
to look something like this (you do not have to use Lombok of course):
private Class<?> scanPackage(String source) {
while (!source.isEmpty()) {
val components = this.scanner.findCandidateComponents(source);
val testConfig = System.getProperties();
val testConfigFile = "test-config.properties";
val applicationClassConfigKey = "main.application.class";
try {
testConfig.load(this.getClass().getResourceAsStream("/" + testConfigFile));
} catch (IOException e) {
logger.error("Error reading configuration file: {}, using default algorithm", testConfigFile);
}
if (testConfig.containsKey(applicationClassConfigKey)) {
if (!components.isEmpty() && testConfig.containsKey(applicationClassConfigKey) && testConfig.getProperty(applicationClassConfigKey) != null) {
boolean found = false;
val configClassName = testConfig.getProperty(applicationClassConfigKey);
for (BeanDefinition component: components) {
if (configClassName.equals(component.getBeanClassName())) {
found = true;
break;
}
}
Assert.state(found,
() -> "Found multiple @SpringBootConfiguration annotated classes "
+ components + ", none of which are of type " + configClassName);
return ClassUtils.resolveClassName(
configClassName, null);
}
} else {
if (!components.isEmpty()) {
Assert.state(components.size() == 1,
() -> "Found multiple @SpringBootConfiguration annotated classes "
+ components);
return ClassUtils.resolveClassName(
components.iterator().next().getBeanClassName(), null);
}
}
source = getParentPackage(source);
}
return null;
}
Check the link for the entire project.
Did you check? @SpringBootTest(classes = {Customer1Application.class, Customer2Application.class})
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.