【问题标题】:Test in spring boot without effect on database在Spring Boot中测试而不影响数据库
【发布时间】:2020-08-02 10:03:40
【问题描述】:

我正在尝试测试我的服务层(实际上是插入),但对我的数据库没有任何影响。 在我的代码中:

@SpringBootTest
@RunWith(SpringRunner.class)
@Transactional
public class StateServiceTest {

@Autowired
private StateService stateService;

@Test
public void createState() {
    State state = State.builder()
            .id(null)
            .name("testState")
            .code("21")
            .build();

    Object mCreatedState = stateService.create(state);
    assertThat(mCreatedState).isNotNull().isNotInstanceOf(Exception.class);
    }

}

使用 @Transactional 可能解决了我的问题,测试数据没有插入数据库,但仍然对我的数据库有影响。

这意味着如果插入的数据存在于数据库中或重复(对于唯一列),我得到错误重复条目键。

有什么方法可以在不影响我的数据库的情况下测试我的服务和 dao 层? 或者我应该使用像 h2 这样的测试数据库(在内存中)?

【问题讨论】:

    标签: spring unit-testing testing


    【解决方案1】:

    如果您想在没有的情况下测试您的服务类。影响数据库,这意味着您正在尝试对服务层进行集成测试。

    Spring 提供的选项之一是@TestPropertSource。您可以在此处覆盖任何属性、定义新属性或定义新 .properties/.yml 文件的位置。

    你可以在你的类中包含 h2 作为测试范围,在 src/test/resources 下提供一个新的 application-test.yml 文件。 在那里定义数据源属性以指向 h2 数据库并继续您的测试。

    以下是一些相关的博客:

    还有另一种称为 TestContaniers 的方法,它启动了一个 db 容器。我个人没有使用过这个,但读过它。 阅读更多关于它们的一个很好的起点是:

    【讨论】:

    • 哪种方式更好?使用 h2 数据库或使用 @TestPropertSource。
    • 没有什么不同。即使您的 cp 中有 h2,当 SpringBootTest 运行时,它也会从 src/main/resources 下的资源文件夹中引导 ApplicationContexy。这意味着,它连接到实际的数据库。所以在你的 cp 中有一个 h2,在 src/test/resources 下的 application-test.yml 中提及 db 详细信息,并使用 @TestProperty 要求 Spring 从测试属性文件加载配置。检查博客,你应该更清楚
    【解决方案2】:

    在测试时最好不要接触任何现有的基础设施。 连接到数据库不仅会出现基于未提供的值的意外行为 bust 还会增加总执行时间。

    如果 DAO 层测试本身就是一个用例,那么请继续使用 H2,它可以让您在没有任何影响的情况下执行所有数据库操作。同时运行整个测试套件的多个测试也不会相互影响。

    H2 的缺点是您有一个单独的数据库架构副本,这可能会增加项目维护。

    模拟外部服务始终是最佳实践。

    【讨论】:

    • 测试完成后有没有办法从h2中删除数据??
    • H2 主要用作内存数据库。 db 的生命周期从应用程序引导期间完成的数据库启动开始,并在应用程序退出时被销毁。在引导过程中,将在 db 中创建表和数据。所有这些都是可配置的。后测试不存在数据库,这意味着不存在任何事务痕迹。简而言之,创建 --> 交易 --> 销毁。如果你想转储数据,你仍然可以这样做。
    • 是的,如果配置测试它会在服务器运行后销毁。谢谢
    【解决方案3】:

    我终于找到了最好的解决方案。

    在阅读了不同的笔记后,我认为最好的解决方案是: 在 H2 或 Fongo 等内存数据库中使用,如果你真的想要这个,你应该像主数据库一样使用 Docker 容器。

    这是因为内存数据库的所有行为可能与您的主数据库不同,如下所示:

    1- Postgres 具有强大的功能,例如 H2 不支持的窗口函数和 JSON 数据类型

    2- 例如,我们想使用 MySQL 的 unix_timestamp() 函数来独立于我们的 MySQL 数据库服务器运行的不同时区。我们希望防止细微的不准确。但是H2中没有这个功能,所以我们不能使用它们

    还有……

    但是如果我们使用与主数据库(Docker 容器)相同的数据库,我们的测试会得到很大改进,最终我们可以防止大多数数据库错误出现在项目构建或部署到主(最终)数据库之后。

    阅读以下参考资料可能会对您有所帮助:

    1-https://phauer.com/2017/dont-use-in-memory-databases-tests-h2/

    2-https://medium.com/@sanchezdale/using-a-containerized-database-for-testing-spring-boot-applications-56ad38d39e15

    希望对某人有所帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-11-16
      • 1970-01-01
      • 1970-01-01
      • 2015-03-21
      • 1970-01-01
      • 2022-01-23
      • 1970-01-01
      相关资源
      最近更新 更多