简体   繁体   English

Spring Boot / JUnit,为多个配置文件运行所有单元测试

[英]Spring Boot / JUnit, run all unit-tests for multiple profiles

I have a BaseTest class which consists of several tests.我有一个 BaseTest 类,它由几个测试组成。 Each test shall be executed for EVERY profile I list.应对我列出的每个配置文件执行每个测试。

I thought about using Parameterized values such as:我考虑过使用参数化值,例如:

@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"))
}

How would I tell Spring to run each test with these different profiles?我如何告诉 Spring 使用这些不同的配置文件运行每个测试? In fact, each profile will talk to different datasources (in-memory h2, external mysql, external oracle, ..) so my repository/datasource has to be reinitialized.事实上,每个配置文件都会与不同的数据源(内存中的 h2、外部 mysql、外部 oracle 等)对话,因此我的存储库/数据源必须重新初始化。


I know that I can specify @ActiveProfiles(...) and I can even extend from BaseTest and override the ActiveProfile annotation.我知道我可以指定 @ActiveProfiles(...) 并且我什至可以从 BaseTest 扩展并覆盖 ActiveProfile 注释。 Although this will work, I only show a portion of my test-suite.虽然这会起作用,但我只展示了我的测试套件的一部分。 Lots of my test-classes extend from BaseTest and I don't want to create several different profile-stubs for each class.我的很多测试类都从 BaseTest 扩展而来,我不想为每个类创建几个不同的配置文件存根。 Currently working, but ugly solution:目前工作,但丑陋的解决方案:

  • BaseTest (@ActiveProfiles("mysql")) BaseTest (@ActiveProfiles("mysql"))
    • FooClassMySQL(annotation from BaseTest) FooClassMySQL(来自BaseTest的注释)
      • FooClassH2(@ActiveProfiles("h2")) FooClassH2(@ActiveProfiles("h2"))
    • BarClassMySQL(annotation from BaseTest) BarClassMySQL(来自 BaseTest 的注释)
      • BarClassH2(@ActiveProfiles("h2")) BarClassH2(@ActiveProfiles("h2"))

Thanks谢谢

If you use Maven you can actually specify active profile from command line (or env variable if needed):如果您使用 Maven,您实际上可以从命令行(或 env 变量,如果需要)指定活动配置文件:

mvn clean test -Dspring.profiles.active=h2-test

The approach with parameterized test may not work in this case, because profile has to be specified before Spring boots up its context.在这种情况下,参数化测试的方法可能不起作用,因为必须在 Spring 启动其上下文之前指定配置文件。 In this case when you run parameterized integration test the context will be already booted up before test runner starts running your test.在这种情况下,当您运行参数化集成测试时,上下文将在测试运行器开始运行您的测试之前已经启动。 Also JUnit's parameterized tests were invented for other reasons (running unit tests with different data series).此外,出于其他原因(使用不同的数据系列运行单元测试),还发明了 JUnit 的参数化测试。

EDIT: Also one more thing - when you decide to use @RunWith(Parameterized.class) you wont be able to use different runner.编辑:还有一件事 - 当您决定使用@RunWith(Parameterized.class)您将无法使用不同的跑步者。 In many cases (if not all if it comes to integration testing) you want to specify different runner, like SpringRunner.class - with parameterized test you wont be able to do it.在许多情况下(如果不是全部,如果涉及集成测试)您想要指定不同的运行程序,例如SpringRunner.class - 使用参数化测试您将无法做到。

Spring profiles are not designed to work in this way. Spring 配置文件并非设计为以这种方式工作。
In your case, each profile uses a specific datasource.在您的情况下,每个配置文件都使用特定的数据源。
So each one requires a Spring Boot load to run tests with the expected datasource.所以每个人都需要一个 Spring Boot 负载来使用预期的数据源运行测试。

In fact, what you want to do is like making as many Maven build as Spring profiles that you want to test.事实上,您想要做的就像制作与您想要测试的 Spring 配置文件一样多的 Maven 构建。

Besides, builds in local env should be as fast as possible.此外,在本地环境中构建应该尽可能快。
Multiplying automated tests execution by DBMS implementation that requires a Spring Boot reload for each one will not help.通过 DBMS 实现乘以自动化测试执行,每个测试都需要重新加载 Spring Boot 将无济于事。

You should not need to specify @ActiveProfiles .您不需要指定@ActiveProfiles

It looks rather like a task for a Continuous Integration tool where you could define a job that executes (sequentially or parallely) each Maven build by specifying a specific Spring Boot profile :它看起来更像是一个持续集成工具的任务,您可以在其中定义一个作业,通过指定特定的 Spring Boot 配置文件来执行(顺序或并行)每个 Maven 构建:

mvn clean test -Dspring.profiles.active=h2

mvn clean test -Dspring.profiles.active=mysql

etc...等等...

You can also try to perform it in local by writing a script that performs the execution of the maven builds.您还可以尝试通过编写执行 maven 构建的脚本在本地执行它。
But as said, it will slowdown your local build and also complex it.但如前所述,它会减慢您的本地构建速度,并使之复杂化。

For what it's worth:对于它的价值:

My use case was to run a specific test class for multiple spring profiles, this is how I achieved it:我的用例是为多个 spring 配置文件运行特定的测试类,这就是我实现它的方式:

@SpringBootTest
abstract class BaseTest {
 @Test void doSomeTest() {... ARRANGE-ACT-ASSERT ...}
}

@ActiveProfiles("NextGen")
class NextGenTest extends BaseTest {}

@ActiveProfiles("Legacy")
class LegacyTest extends BaseTest {}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM