I have a case class that I serialize to JSON, and a test case that checks that round-tripping works.
Buried deep inside the case class are java.time.Instant
s, which I put into JSON as their epoch milliseconds.
Turns out that an Instant
actually has nanosecond precision and that gets lost in translation, making the test fail because the timestamps are slightly off now.
Is there an easy way to make Scalatest ignore the difference? I just want to fix the test, the loss in precision is totally acceptable for the application.
We use Clock.instant to know the current time instead of Instant.now to avoid this problem. So the code for the class should be this way
class MyClass(clock: Clock) {
def getResult(): Result = {
Result(clock.instant)
}
}
and at the test, we mock clock.instant to guarantee we check the exact same time.
class MyClassTest {
val customTime = Instant.now
val clock = mock[Clock]
clock.instant() returns customTime
// test
val myClass = new MyClass(clock)
val expectedResult = Result(customTime)
myClass.getResult ==== expectedResult
}
I am not sure it will help in your situation, but in case and for anyone else reading along: the correct way of comparing two Instant
objects considering only millisecondes and coarser is to truncate each to millisecond precision (here in Java):
Instant instant1 = Instant.parse("2018-12-14T08:25:54.232235133Z");
Instant instant2 = Instant.parse("2018-12-14T08:25:54.232975217Z");
if (instant1.truncatedTo(ChronoUnit.MILLIS).equals(instant2.truncatedTo(ChronoUnit.MILLIS))) {
System.out.println("Equal to the millisecond");
} else {
System.out.println("Not equal to the millisecond");
}
Output:
Equal to the millisecond
If you know for a fact that one of them has already been truncated in its roundtrip through JSON (and you consider it a requirement that it must be), you don’t need to truncate that one again, of course.
Using a Clock
for testing is often a good idea. It can help you write reproducible tests. You can easily have a clock that only counts milliseconds:
Clock c = Clock.tickMillis(ZoneOffset.UTC);
System.out.println(c.instant());
System.out.println(Instant.now(c));
Output when running just now:
2018-12-14T10:48:47.929Z 2018-12-14T10:48:47.945Z
As you see, the generated Instant
objects have only three decimals on the seconds, that is, millisecond precision and nothing finer. When you only use the Clock
for drawing Instant
s, it doesn’t matter which time zone you pass to tickMillis
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With