Spring Boot / JUnit,运行 多个配置文件的所有单元测试
Spring Boot / JUnit, run all unit-tests for multiple profiles
我有一个由多个测试组成的 BaseTest class。应针对我列出的每个配置文件执行每个测试。
我考虑过使用参数化值,例如:
@RunWith(Parameterized.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// @ActiveProfiles("h2-test") // <-- how to iterate over this?
public abstract class BaseTest {
@Autowired
private TestRepository test;
// to be used with Parameterized/Spring
private TestContextManager testContextManager;
public BaseTest(String profile) {
System.setProperty("spring.profiles.active", profile);
// TODO what now?
}
@Parameterized.Parameters
public static Collection<Object[]> data() {
Collection<Object[]> params = new ArrayList<>();
params.add(new Object[] {"h2-test" });
params.add(new Object[] {"mysql-test" });
return params;
}
@Before
public void setUp() throws Exception {
this.testContextManager = new TestContextManager(getClass());
this.testContextManager.prepareTestInstance(this);
// maybe I can spinup Spring here with my profile?
}
@Test
public void testRepository() {
Assert.assertTrue(test.exists("foo"))
}
我如何告诉 Spring 到 运行 使用这些不同配置文件的每个测试?事实上,每个配置文件都会与不同的数据源(内存中的 h2、外部 mysql、外部 oracle,..)对话,所以我的 repository/datasource 必须重新初始化。
我知道我可以指定@ActiveProfiles(...),我什至可以从 BaseTest 扩展并覆盖 ActiveProfile 注释。尽管这可行,但我只展示了我的测试套件的一部分。我的很多测试-classes 都从 BaseTest 扩展而来,我不想为每个 class 创建几个不同的配置文件存根。目前有效,但丑陋的解决方案:
- BaseTest (@ActiveProfiles("mysql"))
- FooClassMySQL(来自 BaseTest 的注解)
- FooClassH2(@ActiveProfiles("h2"))
- BarClassMySQL(来自BaseTest的注解)
- BarClassH2(@ActiveProfiles("h2"))
谢谢
如果您使用 Maven,您实际上可以从命令行(或环境变量,如果需要)指定活动配置文件:
mvn clean test -Dspring.profiles.active=h2-test
参数化测试的方法在这种情况下可能不起作用,因为必须在 Spring 启动其上下文之前指定配置文件。在这种情况下,当您 运行 参数化集成测试时,上下文将在测试 运行ner 开始 运行 测试之前已经启动。此外,由于其他原因发明了 JUnit 的参数化测试(运行使用不同数据系列进行单元测试)。
编辑:还有一件事 - 当您决定使用 @RunWith(Parameterized.class)
时,您将无法使用不同的 运行ner。在许多情况下(如果不是全部,如果涉及到集成测试)你想要指定不同的 运行ner,比如 SpringRunner.class
- 使用参数化测试你将无法做到这一点。
Spring 配置文件不适合以这种方式工作。
在您的情况下,每个配置文件都使用特定的数据源。
所以每个人都需要 Spring 引导加载以 运行 测试预期的数据源。
事实上,您想要做的就像构建与要测试的 Spring 个配置文件一样多的 Maven。
此外,在本地环境中构建应该尽可能快。
通过需要为每个 Spring 引导重新加载的 DBMS 实现来增加自动测试执行将无济于事。
您不需要指定 @ActiveProfiles
。
它看起来更像是一个持续集成工具的任务,您可以在其中定义一个作业,该作业通过指定特定的 Spring 启动配置文件来执行(顺序或并行)每个 Maven 构建:
mvn clean test -Dspring.profiles.active=h2
mvn clean test -Dspring.profiles.active=mysql
等...
您也可以尝试通过编写执行 maven 构建的脚本在本地执行它。
但如前所述,它会减慢您的本地构建速度并使其复杂化。
物有所值:
我的用例是 运行 针对多个 spring 配置文件的特定测试 class,我是这样实现的:
@SpringBootTest
abstract class BaseTest {
@Test void doSomeTest() {... ARRANGE-ACT-ASSERT ...}
}
@ActiveProfiles("NextGen")
class NextGenTest extends BaseTest {}
@ActiveProfiles("Legacy")
class LegacyTest extends BaseTest {}
我有一个由多个测试组成的 BaseTest class。应针对我列出的每个配置文件执行每个测试。
我考虑过使用参数化值,例如:
@RunWith(Parameterized.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
// @ActiveProfiles("h2-test") // <-- how to iterate over this?
public abstract class BaseTest {
@Autowired
private TestRepository test;
// to be used with Parameterized/Spring
private TestContextManager testContextManager;
public BaseTest(String profile) {
System.setProperty("spring.profiles.active", profile);
// TODO what now?
}
@Parameterized.Parameters
public static Collection<Object[]> data() {
Collection<Object[]> params = new ArrayList<>();
params.add(new Object[] {"h2-test" });
params.add(new Object[] {"mysql-test" });
return params;
}
@Before
public void setUp() throws Exception {
this.testContextManager = new TestContextManager(getClass());
this.testContextManager.prepareTestInstance(this);
// maybe I can spinup Spring here with my profile?
}
@Test
public void testRepository() {
Assert.assertTrue(test.exists("foo"))
}
我如何告诉 Spring 到 运行 使用这些不同配置文件的每个测试?事实上,每个配置文件都会与不同的数据源(内存中的 h2、外部 mysql、外部 oracle,..)对话,所以我的 repository/datasource 必须重新初始化。
我知道我可以指定@ActiveProfiles(...),我什至可以从 BaseTest 扩展并覆盖 ActiveProfile 注释。尽管这可行,但我只展示了我的测试套件的一部分。我的很多测试-classes 都从 BaseTest 扩展而来,我不想为每个 class 创建几个不同的配置文件存根。目前有效,但丑陋的解决方案:
- BaseTest (@ActiveProfiles("mysql"))
- FooClassMySQL(来自 BaseTest 的注解)
- FooClassH2(@ActiveProfiles("h2"))
- BarClassMySQL(来自BaseTest的注解)
- BarClassH2(@ActiveProfiles("h2"))
- FooClassMySQL(来自 BaseTest 的注解)
谢谢
如果您使用 Maven,您实际上可以从命令行(或环境变量,如果需要)指定活动配置文件:
mvn clean test -Dspring.profiles.active=h2-test
参数化测试的方法在这种情况下可能不起作用,因为必须在 Spring 启动其上下文之前指定配置文件。在这种情况下,当您 运行 参数化集成测试时,上下文将在测试 运行ner 开始 运行 测试之前已经启动。此外,由于其他原因发明了 JUnit 的参数化测试(运行使用不同数据系列进行单元测试)。
编辑:还有一件事 - 当您决定使用 @RunWith(Parameterized.class)
时,您将无法使用不同的 运行ner。在许多情况下(如果不是全部,如果涉及到集成测试)你想要指定不同的 运行ner,比如 SpringRunner.class
- 使用参数化测试你将无法做到这一点。
Spring 配置文件不适合以这种方式工作。
在您的情况下,每个配置文件都使用特定的数据源。
所以每个人都需要 Spring 引导加载以 运行 测试预期的数据源。
事实上,您想要做的就像构建与要测试的 Spring 个配置文件一样多的 Maven。
此外,在本地环境中构建应该尽可能快。
通过需要为每个 Spring 引导重新加载的 DBMS 实现来增加自动测试执行将无济于事。
您不需要指定 @ActiveProfiles
。
它看起来更像是一个持续集成工具的任务,您可以在其中定义一个作业,该作业通过指定特定的 Spring 启动配置文件来执行(顺序或并行)每个 Maven 构建:
mvn clean test -Dspring.profiles.active=h2
mvn clean test -Dspring.profiles.active=mysql
等...
您也可以尝试通过编写执行 maven 构建的脚本在本地执行它。
但如前所述,它会减慢您的本地构建速度并使其复杂化。
物有所值:
我的用例是 运行 针对多个 spring 配置文件的特定测试 class,我是这样实现的:
@SpringBootTest
abstract class BaseTest {
@Test void doSomeTest() {... ARRANGE-ACT-ASSERT ...}
}
@ActiveProfiles("NextGen")
class NextGenTest extends BaseTest {}
@ActiveProfiles("Legacy")
class LegacyTest extends BaseTest {}