【问题标题】:How to perform integration tests on MySQL service layer and omit the ID of entities?如何对MySQL服务层进行集成测试,省略实体ID?
【发布时间】:2022-11-17 10:02:04
【问题描述】:

我正在编写一个使用 JPA 连接到 MySQL 数据库的 Spring 应用程序。我正在使用 Testcontainers 在我的应用程序的服务层上执行集成测试,它运行得非常顺利。在测试类中,我构建了要存储在数据库中的实体,为此我使用了构建器模式:

private static final OrderDTO VALID_ORDER = OrderDTO.builder()
    .withId(1L) // primary key
    .withOrderId("orderId") // fetched from external API
    .withAddress(validAddress)
    ...
    .build();

然后我有一个测试:

void shouldSaveNewOrder() {
    OrderDTO order = orderService.saveNewOrder(VALID_ORDER);
    assertThat(orderService.findByOrderId("orderId")).isEqualTo(order);
}

我的问题是 - 我有另一个测试类,它也构造 OrderDTO 实体并将它们存储在同一个数据库中,这意味着我必须在测试中对特定 ID 进行硬编码,这样它们就不会在类之间发生冲突。这会在测试类中造成不必要的混淆,因此理想情况下我想从测试中省略 ID,因为它并不重要——我只需要测试其他字段。当然,ID 是主键,所以它不能为 null,所以我不能简单地从构建器中删除 withId()

我的问题是我怎样才能做到这一点?另一个选择是擦除数据库表并在测试类运行后重置自动增量,但是 afaik 将涉及调用 EntityManager 或 JdbcTemplate,我正在 Repository 级别编写此应用程序,所以这似乎不是最好的方法。无论如何,我宁愿进行干净的测试!

【问题讨论】:

    标签: java spring hibernate spring-data-jpa testcontainers


    【解决方案1】:

    AssertJ 提供了非常酷的信息提取功能。看下面的例子

    @Test
    void test() {
        var person = new Person(1l, "Eddú", "Meléndez");
        assertThat(person)
                .extracting(Person::name, Person::lastname)
                .contains("Eddú", "Meléndez");
    
        var expected = new PersonName("Eddú", "Meléndez");
        assertThat(person)
                .extracting(data -> new PersonName(data.name(), data.lastname()), as(InstanceOfAssertFactories.type(PersonName.class)))
                .isEqualTo(expected);
    }
    
    record Person(Long id, String name, String lastname){}
    record PersonName(String name, String lastname){}
    

    第一个断言提取姓名和姓氏并与提供的信息相匹配。第二个,如果你使用夹具数据很有用,允许提取和映射数据,在示例中为PersonName

    【讨论】:

      猜你喜欢
      • 2020-03-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-08
      • 1970-01-01
      • 2013-02-16
      • 2017-07-10
      • 2018-06-11
      相关资源
      最近更新 更多