Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to set @CreatedDate in the past (for testing)

My spring-data-jpa backend has a class that populates the (test) database with a lot of test data. The class usese the spring data repositories to create entities. All my entities have a field annotated with @CreatedData and the corresponding @EntityListeners(AuditingEntityListener.class) annotation on the model class. This works fine so far. dateCreated is automatically set correctly.

But when running Junit test I sometimes need to create a (test) object with a dateCreated in the past. How can I archive this? Only via plain JDBC?

like image 876
Robert Avatar asked Feb 21 '17 17:02

Robert


2 Answers

I found a way that works for me (using plain JDBC):

First I create my domain objects for testing with spring-data-jpa:

MyModel savedModel = myRepo.save(myModel);

That automatically fills the "dateCreated" with timestamp of "now". Since I need creation dates in the past for testing I manually tweak them with plain 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);

Do not forget to also setCreatedAt inside the returned model class.

like image 120
Robert Avatar answered Sep 22 '22 07:09

Robert


In case you are using Spring Boot, you can mock dateTimeProvider bean used in EnableJpaAuditing annotation. Spring Data uses this bean to obtain current time at the entity creation/modification.

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

    @MockBean
    DateTimeProvider dateTimeProvider;

...

It is necessary to define actual testDateTimeProvider bean, but it won't be used at all, as you will use mock instead. You can write mockito methods afterwards as usual:

@Test
public void shouldUseMockDate() {

    when(dateTimeProvider.getNow()).thenReturn(Optional.of(LocalDateTime.of(2020, 2, 2, 0, 0, 0)));
    
   
   ... actual test assertions ...
like image 37
Peter Podhorsky Avatar answered Sep 21 '22 07:09

Peter Podhorsky