jpa 如何在过去设置@CreatedDate(用于测试)

l7mqbcuq  于 2023-05-29  发布在  其他
关注(0)|答案(4)|浏览(203)

我的spring-data-jpa后端有一个类,它用大量的测试数据填充(test)数据库。该类使用spring数据存储库创建实体。我的所有实体都有一个用@CreatedData注解的字段,以及模型类上相应的@EntityListeners(AuditingEntityListener.class)注解。到目前为止,这工作得很好。dateCreated会自动正确设置。
但是当运行Junit test时,我有时需要创建一个dateCreated在过去的(test)对象。我如何存档这个?只通过普通JDBC?

vpfxa7rd

vpfxa7rd1#

如果您使用Sping Boot ,您可以模拟EnableJpaAuditing annotation中使用的dateTimeProvider bean。Spring Data使用此bean获取实体创建/修改时的当前时间。

@Import({TestDateTimeProvider.class})
@DataJpaTest
@EnableJpaAuditing(dateTimeProviderRef = "testDateTimeProvider")
public class SomeTest {

    @MockBean
    DateTimeProvider dateTimeProvider;

...

有必要定义实际的testDateTimeProviderbean,但它根本不会被使用,因为您将使用mock。你可以像往常一样编写mockito方法:

@Test
public void shouldUseMockDate() {

    when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2020, 2, 2, 0, 0, 0)));
    
   
   ... actual test assertions ...
nukf8bse

nukf8bse2#

我找到了一种适合我的方法(使用普通JDBC):
首先,我使用spring-data-jpa创建我的域对象进行测试:

MyModel savedModel = myRepo.save(myModel);

这会自动用“now”的时间戳填充“dateCreated”。因为我需要过去的创建日期来进行测试,所以我用普通JDBC手动调整它们:

@Autowired
JdbcTemplate jdbcTemplate;

[...]

// This syntax is for H2 DB.  For MySQL you need to use DATE_ADD
String sql = "UPDATE myTable SET created_at = DATEADD('DAY', -"+ageInDays+", NOW()) WHERE id='"+savedLaw.getId()+"'";
jdbcTemplate.execute(sql);
savedModel.setCreatedAt(new Date(System.currentTimeMillis() - ageInDays* 3600*24*1000);

不要忘记在返回的模型类中也设置CreatedAt。

0yg35tkg

0yg35tkg3#

我不知道你正在使用的确切测试用例,但我可以看到一些解决方案:

  • 创建一个mock对象,一旦dateCreated被调用,返回一个月前的日期
  • 可能使用in-mem数据库,在测试前用日期填充它
  • 从注解中提供的链接使用AOP
uxhixvfz

uxhixvfz4#

我发现使用Mockito的最好和最干净的方法是在保存之前更改AuditingHandler,方法是设置DateTimeProvider的旧实现。从Java 8开始,这可以使用Lambda接口来完成:

@SpyBean
private AuditingHandler auditingHandler;

// inside the test
auditingHandler.setDateTimeProvider(() -> Optional.of(YOUR_DATE));
savedEntity = repository.save(entity);

相关问题