Alternative to @DirtyContext for isolated JUnit tests under spring boot with H2 in memory db

huangapple go评论60阅读模式
英文:

Alternative to @DirtyContext for isolated JUnit tests under spring boot with H2 in memory db

问题

现在我在我的JUnit测试类中使用 `@DirtiesContext(classMode=DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)`,但我认为这种方法过于过度而且增加了比必要更多的工作量和开销),因为整个上下文将在每个测试案例之前重新创建我唯一需要的是`@DirtiesContext`注释是我的内存中的H2数据库在每个测试方法之前都应该是空的并且重新创建的有没有一种简单的方法在每个测试案例开始时自动创建一个新的空的H2数据库

附注我认为通过手动编写一个清空数据库的`@Before`注释方法在应用程序随着100多个表等的增长时是不可扩展的

当前代码示例

__*测试类*__

```Java
@SpringBootTest
@ExtendWith(SpringExtension.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
@ActiveProfiles("test")
@Slf4j
public class TestClass {

    @Test
    @DisplayName("检查 X 是否已保存在数据库中")
    public void doXTest() {
        // 进行独立的测试等等
    }

    @SneakyThrows
    @Test
    @DisplayName("执行 y")
    public void doYTestMethod() {
        // 进行独立的测试
    }
}

application.yml

spring:
  datasource:
    url: jdbc:h2:mem:template-db
    driver-class-name: org.h2.Driver
    username: XXXXXXX
    password: XXXXXXX
    h2:
    console:
      enabled: true
      path: /h2-console
    jpa:
      database-platform: org.hibernate.dialect.H2Dialect

<details>
<summary>英文:</summary>

Right now I&#39;m using `@DirtiesContext(classMode=DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)` in my JUnit-Testclasses, but I think this approach is way to overkill and also does add way more workload (and overhead) than needed, since the whole context will be recreated before each test case. The only thing I need out of the Annotation `@DirtiesContext` is that my in memory H2 database should be empty and recreated before each test method. Is there an easy way to automatically start each test case with a newly created and empty h2 Database? 

PS: I think doing a `@Before` annotated method that clears the db by hand is not scaleable when the application will grow with over 100+ tables etc.

Current code example:

__*Testclass*__

```Java
@SpringBootTest
@ExtendWith(SpringExtension.class)
@DirtiesContext(classMode = DirtiesContext.ClassMode.BEFORE_EACH_TEST_METHOD)
@ActiveProfiles(&quot;test&quot;)
@Slf4j
public class TestClass {

    @Test
    @DisplayName(&quot;Check if X is saved in database&quot;)
    public void doXTest() {
        // do tests etc isolated 
    }

    @SneakyThrows
    @Test
    @DisplayName(&quot;Do y&quot;)
    public void doYTestMethod() {
        // do test isolated with 
    }
}

application.yml

spring:
  datasource:
    url: jdbc:h2:mem:template-db
    driver-class-name: org.h2.Driver
    username: XXXXXXX
    password: XXXXXXX
    h2:
      console:
        enabled: true
        path: /h2-console
    jpa:
      database-platform: org.hibernate.dialect.H2Dialect

答案1

得分: 3

你可以使用@Transactional注解来标记你的测试类,这将导致每个测试在一个事务中运行,并在每个测试后回滚。这应该在每个测试后保持数据库表的干净状态,不需要为每个测试重新创建数据库(因为这也相当昂贵)。

如果你正在使用@DataJpaTest,它已经包含了@Transactional注解。

英文:

You can annotate your test class with @Transactional and this will result that each test will run in a transaction that is rolled back after each test. This should leave the database tables in a clean test after each test and there shouldn't be a need to re-create the database for each test (as it's also rather expensive).

If you are using @DataJpaTest this already comes with the @Transactional annotation.

huangapple
  • 本文由 发表于 2020年8月12日 04:23:57
  • 转载请务必保留本文链接:https://go.coder-hub.com/63365874.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定