Протестируйте Android DecimalFormat с помощью Robolectric

Библиотека Android изменила класс DecimalFormat, добавив несколько приятных дополнений. Конечно, мне нужно одно из этих дополнений (обозначение значащей цифры: @).

Когда я тестирую Robolectric, кажется, что стандартный Java Используется класс DecimalFormat, из-за чего мои тесты не выполняются.

Есть ли способ заставить Robolectric использовать версию для Android? Или я должен включить DecimalFormat в свой проект (скопировать/вставить класс из AOSP?)?

Вот урезанный пример:

Если я запускаю приложение на устройстве со следующим:

import java.text.DecimalFormat;
import java.util.Locale;

public class App extends Application {
    @Override
    public void onCreate() {
        super.onCreate();
        DecimalFormat decimalFormat = (DecimalFormat)java.text.NumberFormat.getInstance(Locale.US);
        decimalFormat.applyPattern("@@@");
        Log.d('SO', decimalFormat.format(0.0567467));
    }
}

Он отображает:

С приложением: 0,0567

В модульных тестах:

import org.junit.Test;
import org.junit.runner.RunWith;
import org.robolectric.RobolectricGradleTestRunner;
import org.robolectric.annotation.Config;
import java.text.DecimalFormat;
import java.util.Locale;

import static junit.framework.TestCase.assertEquals;


@RunWith(RobolectricGradleTestRunner.class)
@Config(constants = BuildConfig.class, sdk = 21)
public class NumberFormatTest {
    @Test
    public void testSignificantDigit() {
        DecimalFormat decimalFormat = (DecimalFormat)java.text.NumberFormat.getInstance(Locale.US);
        decimalFormat.applyPattern("@@@");
        assertEquals("0.0567", decimalFormat.format(0.0567467));
    }
}

Запуск теста выведет:

junit.framework.ComparisonFailure:

Ожидаемый: 0,0567

Фактический :@@@0


person fstephany    schedule 30.09.2015    source источник
comment
определить: заставляет мои тесты провалиться , с некоторыми приятными дополнениями ... добавить немного кода ...   -  person Selvin    schedule 30.09.2015
comment
Покажите нам минимальный тест, который демонстрирует проблему. Это будет семя для полезного ответа. Включите любые робоэлектрические атрибуты в тестовый класс.   -  person weston    schedule 30.09.2015
comment
поскольку format() возвращает StringBuffer, вы пытались вызвать для него toString?   -  person Shine    schedule 30.09.2015
comment
@Selvin с некоторыми приятными дополнениями. Ссылка на фактическое дополнение Android была в исходном вопросе. Но вы правы, я добавил простой тестовый пример, чтобы проиллюстрировать проблему.   -  person fstephany    schedule 30.09.2015
comment
@Shine, сигнатура метода final String format(double value). Существуют и другие методы форматирования, которые возвращают StringBuilder, но я не использовал их. Тем не менее, я пробовал toString(), но тест дал тот же сбой.   -  person fstephany    schedule 30.09.2015
comment
Воспроизведено и задано github.com/robolectric/robolectric/issues/2071   -  person Eugen Martynov    schedule 02.10.2015


Ответы (1)


Как указано в официальной документации по Android, реализация, предлагаемая при запуске кода Java в Android RunTime (ART) отличается от обычного JVM.

RoboElectric запускает тесты не на обычном телефоне Android или эмуляторе, а на JVM. Эта JVM, работающая в вашей хост-системе, не имеет этой модифицированной версии реализации DecimalFormat во время выполнения. Поэтому, насколько мне известно, функциональные возможности, предлагаемые Android, недоступны при запуске вашего тестового кода в JVM. Чтобы иметь возможность использовать его, запустите свои тесты на телефоне Android, но тогда вы все равно можете избавиться от RoboElectric для этого теста, но используйте предлагаемые инструменты тестирования.

Еще один логичный вопрос: зачем вам тестировать классы Android? Я предполагаю, что Google уже написал тесты для этих изменений и отслеживает их, так что -java-apps/" rel="nofollow">вы не должны тестировать функции, предлагаемые используемой вами системой.

person Capricorn    schedule 30.09.2015
comment
Это именно тот вопрос: Есть ли способ заставить Robolectric использовать версию для Android? Или я должен включить DecimalFormat в свой проект (скопировать/вставить класс из AOSP?)? Предоставленный пример тривиален, он предназначен только для демонстрации поведения сбоя. В моем приложении используется сложная схема форматирования чисел. Я хочу быть уверен, что правильный выбран в правильном случае. У меня есть еще один набор тестов, который работает на Espresso, но мое внутреннее чувство подсказывает мне, что форматирование чисел относится к модульным тестам. - person fstephany; 30.09.2015
comment
Если вы хотите убедиться, что выбран правильный формат, проверьте это! Затем ваш тест должен убедиться, что правильная строка формата выбрана/возвращена вашей функцией selectCorrectFormat. Нет необходимости тестировать само форматирование, так как это часть системы Android. - person Capricorn; 30.09.2015
comment
Возможно, вам не потребуется использовать другую стороннюю библиотеку, такую ​​как эспрессо, но вы можете использовать Инструментальные модульные тесты Android - person Capricorn; 30.09.2015
comment
Да, это то, к чему я пришел: тестирование генерации шаблонов. Но это делает уродливые нечитаемые модульные тесты. Они не имеют никакого смысла для ученых, просматривающих тесты (что они делают часто, поскольку приложение требует больших вычислений). Это похоже на тестирование регулярных выражений, мне нравится добавлять некоторые примеры/угловые случаи только для иллюстрации. - person fstephany; 30.09.2015