Как выполнить модульное тестирование кода, который использует ZoneId.systemDefault, не вызывая org.threeten.bp.zone.ZoneRulesException - PullRequest
0 голосов
/ 27 октября 2018

У меня есть следующий код приложения.

Код приложения

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;
}

Я написал для него модульный тест со следующим:

Код модульного теста

@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);

Я получил следующую ошибку

org.threeten.bp.zone.ZoneRulesException: No time-zone data files registered

Я пытался исправить это с помощью

Код юнит-теста

@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 получение

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)

Можно ли как-нибудь пройти модульный тест, не меняя сигнатуру метода моего текущего приложения?Я хотел бы просто сохранить свою текущую подпись метода приложения без каких-либо изменений.

long advanceByMax1HourWithoutOverflow(long currentTimeMillis)

Обратите внимание, что я использую для модульного тестирования gradle:

implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1'

testImplementation 'junit:junit:4.12'
testImplementation 'org.mockito:mockito-core:2.19.0'

1 Ответ

0 голосов
/ 31 октября 2018

ThreeTen-Android Backport предоставляет бэкпорт классов даты и времени Java SE 8 для системы Android, которая не поддерживает Java 8. Причина этой проблемы заключается в том, что модульный тест выполняется на JVM, а не на Android согласно Android-разработчик :

Модульные тесты, которые запускаются только на вашем локальном компьютере. Эти тесты скомпилированы для локального запуска на виртуальной машине Java (JVM), чтобы минимизировать время выполнения. Если ваши тесты зависят от объектов в платформе Android, мы рекомендуем использовать Robolectric. Для тестов, которые зависят от ваших собственных зависимостей, используйте фиктивные объекты для эмуляции поведения ваших зависимостей.

Джейк Уортон (владелец ThreeTen-Android Backport) о том, что Robolectric не основал ресурсы, сказал :

Это ошибка Robolectric. Либо доложите им, либо переключитесь на использование обычный ThreeTenBP в ваших юнит-тестах. Или оба!

В результате мы должны решить эту проблему, используя оригинальную библиотеку ThreeTen Backport. Поэтому мы должны добавить его зависимость в файл build.gradle, который будет использоваться модульным тестом.

В файле build.gradle:

dependencies {

    implementation 'com.jakewharton.threetenabp:threetenabp:1.1.1'

    testImplementation ('org.threeten:threetenbp:1.3.2'){
        exclude group:'com.jakewharton.threetenabp', module:'threetenabp'
    }
}

В классе модульных испытаний:

@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);
}

Результат:

enter image description here

...