我正在尝试为我的项目实施基于 CSV 的测试。(因此在 test 文件夹中添加带有输入数据的 CSV 将导致 maven 启动新测试)。
现在我使用 SpringJUnitConfig 并使用 @Primary 覆盖项目设置。这是代码:(它会根据测试设置启动一个测试)
package com.bch.score.test.framework;
@SpringJUnitConfig({FrameworkSpringContext.class})
public class MySingleTestLauncher {
@Autowired
public MainApplicationService service;
@Autowired
public TestDbService dbPreparationService;
@Autowired
public IFrameworkDatabaseConfig dbSettings;
@Autowired
public TestOutputChecker outputChecker;
@Test
public void testSingleCase() {
dbPreparationService.fillDatabase(dbSettings);
service.launchApp();
outputChecker.checkResult();
}
}
在我的 FrameworkSpringContext.class 中,我声明了应用程序包和测试包的组件扫描:
@Configuration
@EnableAutoConfiguration(exclude={DataSourceAutoConfiguration.class})
@ComponentScan(value = {"com.bch.score.test.framework.config", "com.bch.score.cmd"})
public class FrameworkSpringContext {
private final ISettingsProvider settings;
@Autowired
public FrameworkSpringContext(ISettingsProvider settings) {
this.settings = settings;
}
@Bean
public TestDbService service() {
return new TestDbService();
}
@Bean
public TestOutputChecker outputAssertion() {
return new TestOutputChecker();
}
@Bean
public IFrameworkDatabaseConfig dbSettings() {
return new FrameworkDatabaseConfigImpl(settings.getUrl(), settings.getSchema(), settings.getLogin(), settings.getPassword());
}
}
我还覆盖了在应用程序内部使用的设置 bean:
@PropertySource("classpath:score-framework.properties")
@Configuration
public class SettingsConfigurationFramework {
@Primary
@Bean(name = "testSettings")
public ISettingsProvider settingsProvider(MessageSource messageSource, Environment environment) {
return new SettingsProviderImpl(messageSource, environment);
}
}
它运行良好,但使用这种方法,我需要为每个新测试复制 MySingleTestLauncher 和配置类。我想要的是使用@TestFactory,在每个文件夹的基础上创建测试。我想象测试启动器看起来像这样:
@SpringJUnitConfig({FrameworkSpringContext.class})
public class MultipleTestLauncher {
@Autowired
public TestDbService dbPreparationService;
@Autowired
public Function<String, IFrameworkDatabaseConfig> dbSettingsFactory;
@Autowired
public TestOutputChecker outputChecker;
@TestFactory
public Collection<DynamicTest> testTests() throws IOException {
List<Path> subFolders = Files.list(Paths.get("src", "test", "resources", "framework", "tests"))
.filter(path -> path.getFileName().toString().startsWith("test_"))
.collect(Collectors.toList());
List<DynamicTest> dynamicTests = new ArrayList<>();
for (Path testPath : subFolders) {
String currentTestFolder = testPath.getFileName().toString();
dynamicTests.add(DynamicTest.dynamicTest(currentTestFolder, () -> {
IFrameworkDatabaseConfig dbSettings = dbSettingsFactory.apply(currentTestFolder);
dbPreparationService.fillDatabase(dbSettings);
//TODO somehow create new Spring context for each app launch...
//TODO getTestContext().getBean(MainApplicationService.class).launchApp();
outputChecker.checkResult();
}));
}
}
}
每个测试都像是一个新的应用程序启动。我希望将它们分开,以确保测试不会混淆彼此的输出。每个测试使用不同的 spring 上下文,我可以轻松地根据测试设置模拟 ISettingsProvider,并实现不同的断言。
所以我的问题是:为动态创建的测试初始化 spring 上下文的最佳实践是什么?
我应该查看上下文缓存(下面的链接)吗?
https://docs.spring.io/spring-framework/docs/4.2.0.RC2/spring-framework-reference/html/integration-testing.html#testcontext-ctx-management-caching
在我看来,创建新的应用程序上下文将是正确的做法,隔离每个测试应用程序启动,因此缓存可能不是这里的最佳选择。