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

问题描述:

我有一个BaseTest类,它由几个测试组成。每个测试都应针对每个配置文件I列表执行。Spring Boot/JUnit,运行多个配置文件的所有单元测试

我想过使用参数值,如:

@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,...)进行通信,因此我的存储库/数据源必须重新初始化。


我知道,我可以指定@ActiveProfiles(...),我甚至可以从BaseTest延伸和覆盖ActiveProfile注解。虽然这会起作用,但我只显示我的测试套件的一部分。很多我的测试类都是从BaseTest扩展而来的,我不想为每个类创建几个不同的配置文件存根。目前的工作,但丑陋的解决方案:

  • BaseTest(@ActiveProfiles( “MySQL的”))
    • FooClassMySQL(注释从BaseTest)
      • FooClassH2(@ActiveProfiles( “H2”))
    • BarClassMySQL(注释从BaseTest)
      • BarClassH2(@ActiveProfiles( “H2”))

感谢

+0

为什么不用参数运行所有测试,例如如果你使用Maven,它可能是'mvn test -Dspring.profiles.active = test'。我不确定你是否可以通过这个参数化的类来实现它,主要是因为在它开始执行测试之前,Spring很可能会启动它的上下文,并且在此之前必须设置活动配置文件。 –

+0

谢谢。非常好的解决方案,我没有想过。如果没有一种优雅的方式来处理它,这肯定会做到!我认为唯一的问题可能是只有少数测试(实际上,我所有的存储库/ jpa测试)需要不同的配置文件,而其他的则不需要访问不同的配置。 – Frame91

+0

酷!如果它适用于您,我会将其添加为答案。 –

如果你使用Maven,你实际上可以从指定命令行(或者,如果环境变量活动的配置文件需要):

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

带参数化测试的方法可能不起作用在这种情况下,因为配置文件必须在Spring启动它的上下文之前指定。在这种情况下,当您运行参数化集成测试时,在测试运行器开始运行测试之前,上下文已经启动。此外,JUnit的参数化测试是由于其他原因(运行具有不同数据系列的单元测试)而发明的。

编辑:还有一件事 - 当你决定使用@RunWith(Parameterized.class)你将无法使用不同的亚军。在许多情况下(如果不是全部涉及集成测试),您希望指定不同的参赛者,例如SpringRunner.class - 通过参数化测试,您将无法做到这一点。

+0

我编辑了我的代码,显示了如何解决SpringRunner.class(实质上使用TestContextManager来) – Frame91

春季配置文件不旨在以这种方式工作。
就你而言,每个配置文件使用特定的数据源。
因此,每个人都需要Spring Boot加载来运行预期数据源的测试。

事实上,你想要做的就像创建与你想测试的Spring配置文件一样多的Maven构建。

此外,建立本地环境应该尽可能快。
通过DBMS实现乘以自动化测试执行,需要每次执行Spring Boot重新加载都无济于事。

您不应指定@ActiveProfiles

它看起来有点像一个持续集成工具,您可以定义执行作业(顺序或平行)每个Maven构建通过指定一个特定的春天引导配置任务:

mvn clean test -Dspring.profiles.active=h2 

mvn clean test -Dspring.profiles.active=mysql 

等..

你也可以尝试通过编写执行maven构建的脚本来在本地执行它。但是如上所述,它会减慢你的本地构建并且使它复杂化。