gpt4 book ai didi

java - 如何伪造单元测试的最后修改时间?

转载 作者:行者123 更新时间:2023-12-05 04:55:58 28 4
gpt4 key购买 nike

我有一个简单的实体,要求上次修改时间应持续更新。

@Data      // Lombok thing
@Entity
@Table(name = "MY_ENTITY")
public class MyEntity {

@Column(name = "LAST_MODIFIED", nullable = false)
private LocalDateTime lastModified;

// irrelevant columns including id omitted

@PrePersist
public void initializeUUID() {
lastModified = LocalDateTime.now();
}
}

我需要实现一个作业来查询早于特定时间(比如说一天)的此类实体,修改其状态并持久化它们。我在为涵盖此类用例的单元测试创​​建数据时遇到问题。

尽管我手动设置了 lastModified 时间,但无论设置值如何,@PrePersist 都会导致其更改。

@Autowired  // Spring Boot tests are configured against in-memory H2 database
MyEntityRepository myEntityRepository;
var entity = new MyEntity();
entity.setLastModified(LocalDateTime.now().minusDays(3));
myEntityRepository.entity(entity);

问题:如何在不为了单元测试而大幅修改 MyEntity 类的情况下准备预先保存的数据 (lastModified)?欢迎使用 Mockito 的解决方案。

注意我使用 Spring Boot + jUnit 5 + Mockito

我尝试过的事情:

  • How to mock persisting and Entity with Mockito and jUnit :模拟持久化实体不是一种可行的方法,因为我需要将实体持久化在 H2 中以进行进一步检查。此外,我尝试通过这个技巧来使用 spy bean Spring Boot #7033结果相同。

  • Hibernate Tips: How to activate an entity listener for all entities :使用为单元测试范围配置的静态嵌套类 @TestConfiguration 以编程方式添加监听器。根本不调用这个东西。

    @TestConfiguration
    public static class UnitTestConfiguration { // logged as registered

    @Component
    public static class MyEntityListener implements PreInsertEventListener {

    @Override
    public boolean onPreInsert(PreInsertEvent event) { // not called at all
    Object entity = event.getEntity();
    log.info("HERE {}" + entity); // no log appears
    // intention to modify the `lastModified` value
    return true;
    }
    }
  • 肮脏的方式:创建一个方法级类扩展 MyEntity@PrePersist “覆盖” lastModified 值。它导致 org.springframework.dao.InvalidDataAccessApiUsageException。要修复它,此类实体依赖于 @Inheritance 注释 ( JPA : Entity extend with entity ),我不想仅仅为了单元测试而使用它。不得在生产代码中扩展该实体。

最佳答案

您可以使用 Spring Data JPA AuditingEntityListener .

只需通过 @org.springframework.data.jpa.repository.config.EnableJpaAuditing 启用它,并可选择提供自定义 dateTimeProviderRef,如下所示:

@Configuration
@EnableJpaAuditing(dateTimeProviderRef = "myAuditingDateTimeProvider")
public class JpaAuditingConfig {

@Bean(name = "myAuditingDateTimeProvider")
public DateTimeProvider dateTimeProvider(Clock clock) {
return () -> Optional.of(now(clock));
}
}

那么您的实体可能看起来像这样:

@Data      // Lombok thing
@Entity
@Table(name = "MY_ENTITY")
@EntityListeners(AuditingEntityListener.class)
public class MyEntity {

@LastModifiedDate
private LocalDateTime lastModified;

// irrelevant columns including id omitted
}

在上面的示例中,可以通过 Spring 提供 java.time.Clock,这已经可以解决您关于测试的问题。但您也可以提供专用的测试配置,指定不同的/模拟的 DateTimeProvider

请注意,这里提到的解决方案不是纯单元测试方法。但根据您的问题和您尝试过的事情,我得出结论,使用 Spring 的解决方案是可行的。

关于java - 如何伪造单元测试的最后修改时间?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65106779/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com