我有一个简单的实体,它要求在persist上更新上次修改的时间。
@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);
问题:如何准备预持久化数据( lastModified
)而不是彻底改变 MyEntity
只是为了单元测试?欢迎使用mockito的解决方案。
注意我使用springboot+junit5+mockito
我尝试过的事情:
如何用mockito和junit来模拟持久化和实体:模拟持久化实体不是一个好办法,因为我需要将实体持久化到h2中进行进一步检查。此外,我还尝试使用spy bean使用这个技巧spring boot#7033,得到了相同的结果。
hibernate提示:如何为所有实体激活实体侦听器:使用配置的静态嵌套类以编程方式添加侦听器 @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),我不想仅仅为了单元测试而使用它。不能在生产代码中扩展实体。
2条答案
按热度按时间qkf9rpyu1#
有了Mockito你也许可以做这样的事?
但我不确定它到底适合你的测试。
另外两个选择
嘲弄
LocalDateTime.now()
让它返回你想要的值。但是,persist进程中的其他代码可能会调用此方法,并且可能不喜欢它。如果是这样的话,就转到另一个选项包裹
LocalDateTime.now()
在您自己的类中使用一个静态方法并模拟它。遗憾的是,它只涉及对实体类的微小更改,但只涉及对LocalDateTime.now()
会被嘲笑的。在这个例子中,我没有描述如何使用mockito进行模拟,因为我不熟悉它。我只用过jmockit。但以上就是原则。
fdbelqdn2#
您可以使用spring数据jpa auditingentitylistener。
只需通过
@org.springframework.data.jpa.repository.config.EnableJpaAuditing
并提供自定义dateTimeProviderRef
这样地:你的实体可以是这样的:
在上面的例子中
java.time.Clock
可以通过spring提供,它已经可以解决您关于测试的问题。但是您也可以提供一个专用的测试配置来指定不同的/mockDateTimeProvider
.请注意,这里提到的解决方案不是纯单元测试方法。但是基于你的问题和你尝试过的事情,我得出结论,使用spring的解决方案是可行的。