Search code examples
javaspring-bootintegration-testingsimpledateformatassertj

Date format in the spring boot repository testing


I am using the following codes to do the integration testing for repository functions. However, it will fail because of the date formart. The output from SimpleDateFormat is 'Wed Jan 01 10:10:10 MST 2020', but the date from database is '2020-01-01 10:10:10.0'. Is their any easy way to handle this issue?

      Optional<TestBean> testBean = testBeanRepository.findById(1L);
      TestBean toReturn = new TestBean();
      toReturn.setAccountNumber(123456789);
      toReturn.setId(1L);
      toReturn.setCustomerName("Peter");
      toReturn.setModifiedDate(new SimpleDateFormat("yyyy-mm-dd HH:mm:ss").parse("2020-01-01 10:10:10"));
      assertThat(testBean)
         .isPresent()
         .hasValue(toReturn);

This is how I defined modified date(java.util.date):

@Column(name = "MODIFIED_DATE_TIME") 
@NotNull 
@Temporal(TemporalType.TIMESTAMP) 
private Date modifiedDate;

Solution

  • It would seem to me that TestBean is declared to hold a java.util.Date, but the TestBean instance returned from findById() instead holds a java.sql.Timestamp. It’s very unfortunate (if it’s true).

    Timestamp is implemented as a subclass of Date. Both classes are poorly designed and long outdated, we should not use them anymore. In spite of the subclass relationship, accordindg to the documentation we should not regard Timestamp as a kind of Date. Implementing Timestamp as a subclass of Date is a true hack. And putting a Timestamp into a Date field in your object is wrong. I also don’t think it was ever the intention that we should use Timestamp in our model beans. It was for transferring data to and from SQL database columns with datatype timestamp and timestamp with time zone only.

    So the good solution is: Change your TestBean class to hold a modern date-time object belonging to a class of java.time, the modern Java date and time API. Edit: Since your datatype in MySQL is datetime, the best match in Java is LocalDateTime. A LocalDateTime is a date and time of day without time zone or UTC offset.

    If you cannot change the type declared in the TestBean class, there are still a couple of possible improvements:

    • Make sure the object holds a Date object as it’s declared to do, not a Timestamp.
    • Add a getter and setter that return and accept an Instant rather than a Date so that your class can better interoperate with code using java.time. The new methods would do the necessary conversion. Then use the new setter for setting the value in toReturn.

    If you can’t do any of this either and you’re forced to being part of the hack, there are of course ways to set modifiedDate to an old-fashioned Timestamp. I suggest:

        toReturn.setModifiedDate(Timestamp.from(Instant.parse("2020-01-01T17:10:10Z")));
    

    I have given the time as 17:10:10. This time is in UTC (denoted by the Z). I assumed that the MST mentioned in your question is North American Mountain Standard Time (not Malaysian Standard Time?), and if so, this time corresponds to the desired 10:10:10 in your time zone.

    Links