I have the following application code.
public static long advanceByMax1HourWithoutOverflow(long currentTimeMillis) {
ZoneId zoneId = ZoneId.systemDefault();
ZonedDateTime zonedDateTime = Instant.ofEpochMilli(currentTimeMillis).atZone(zoneId);
// 0-23
int hour = zonedDateTime.getHour();
if (hour < 23) {
zonedDateTime = zonedDateTime.plusHours(1);
return zonedDateTime.toInstant().toEpochMilli();
}
// 0-59
int minute = zonedDateTime.getMinute();
if (minute < 59) {
zonedDateTime = zonedDateTime.plusMinutes(1);
return zonedDateTime.toInstant().toEpochMilli();
}
return currentTimeMillis;
}
I wrote a unit test for it with the following.
@Test
public void advanceByMax1HourWithoutOverflow() {
/*
27 October 2018
1540648800000 -> 1540652400000
22:00 -> 23:00
*/
long currentTimeMillis = 1540648800000L;
long expected = 1540652400000L;
long output = Utils.advanceByMax1HourWithoutOverflow(currentTimeMillis);
assertEquals(expected, output);
I got the following error
org.threeten.bp.zone.ZoneRulesException: No time-zone data files registered
I tried to fix it by using
@Test
public void advanceByMax1HourWithoutOverflow() {
Context context = mock(Context.class);
AndroidThreeTen.init(context);
/*
27 October 2018
1540648800000 -> 1540652400000
22:00 -> 23:00
*/
long currentTimeMillis = 1540648800000L;
long expected = 1540652400000L;
long output = Utils.advanceByMax1HourWithoutOverflow(currentTimeMillis);
assertEquals(expected, output);
I'm getting
java.lang.ExceptionInInitializerError
at org.threeten.bp.ZoneRegion.ofId(ZoneRegion.java:143)
at org.threeten.bp.ZoneId.of(ZoneId.java:358)
at org.threeten.bp.ZoneId.of(ZoneId.java:286)
at org.threeten.bp.ZoneId.systemDefault(ZoneId.java:245)
Is there any way I can pass the unit test, without changing my current app's method signature? I would like to just retain my current app method signature without any modification.
long advanceByMax1HourWithoutOverflow(long currentTimeMillis)
Note, the gradle which I use for unit testing are
implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1'
testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.19.0'
The systemDefault() method of the ZoneId class in Java is used to return the system default time-zone. Syntax: public String systemDefault() Parameters: This method does not accepts any parameters. Return Value: This method returns the zone ID.
ThreeTen-Android Backport provides a backport of the Java SE 8 date-time classes to Android system which does not support Java 8. The cause of this issue is that the unit test runs on JVM, not Android according to android developer:
Unit tests that run on your local machine only. These tests are compiled to run locally on the Java Virtual Machine (JVM) to minimize execution time. If your tests depend on objects in the Android framework, we recommend using Robolectric. For tests that depend on your own dependencies, use mock objects to emulate your dependencies' behavior.
Jake Wharton (ThreeTen-Android Backport owner) about not founding resources by Robolectric has said:
This is a Robolectric bug. Either report to them or switch to use the normal ThreeTenBP in your unit tests. Or both!
As a result we should solve this problem by using original ThreeTen Backport library. So we should add its dependency to the build.gradle
file to be used by unit test.
In build.gradle file:
dependencies {
implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1'
testImplementation ('org.threeten:threetenbp:1.3.2'){
exclude group:'com.jakewharton.threetenabp', module:'threetenabp'
}
}
In unit test class:
@Test
public void advanceByMax1HourWithoutOverflow() {
/*
27 October 2018
1540648800000 -> 1540652400000
22:00 -> 23:00
*/
long currentTimeMillis = 1540648800000L;
long expected = 1540652400000L;
long output = Utils.advanceByMax1HourWithoutOverflow(currentTimeMillis);
assertEquals(expected, output);
}
Result:
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