2016-10-29 4 views
5

Я совершенно новый для android и пытаюсь понять, как работает пакет.Android Bundle простой модульный тест не работает

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

@Test 
public void testBundle() throws Exception { 
    Bundle bundle = new Bundle(); 
    String key = "hello"; 
    String value = "world"; 
    bundle.putString(key, value); 
    Assert.assertEquals(value, bundle.getString(key)); 
} 

junit.framework.ComparisonFailure: 
Expected :world 
Actual :null 
+0

Какую среду вы используете? Инструментальный тест, Robolectric, JUnit, другой? – Vasiliy

+0

Привет vasiliy junit test –

ответ

5

Тесты JUnit запускаются на локальной машине, на которой нет всего исходного кода Android, но только классы-заглушки (описано here). Эти классы-заглушки позволяют вам скомпилировать Android-приложение против них (потому что их API идентичен реальной платформе Android), но они не содержат никакой логики, чтобы сделать их «легкими».

По умолчанию при попытке вызвать любой из методов заглушки вы получаете исключение. Что-то вроде этого:

public Bundle() { 
    throw new RuntimeException("Stub!"); 
} 

этот «провал быстро» подход был использован для того, чтобы предотвратить разработчик от случайного запуска своего кода против этих классов заглушек, а затем интересно, почему он не работает.

Однако это поведение можно изменить с помощью этой конфигурации в build.gradle:

android { 
    ... 
    testOptions { 
    unitTests.returnDefaultValues = true 
    } 
} 

это делает методы заглушки возвращают значение по умолчанию, вместо того, чтобы бросать исключения.

У вас, вероятно, включена эта функция, поэтому при запуске тестов JUnit вы не получите исключение, но метод Bundle#getString() просто возвращает значение по умолчанию (которое равно null).

Если вы хотите проверить код, который имеет Android рамочной зависимости, вы должны сделать что-либо из:

  1. Mock этих зависимостей (например, Mockito)
  2. испытаний Run с Robolectric
  3. Run инструментальных тестов на Android устройство

В любом случае unitTests.returnDefaultValues = true ОПИСАНИЕ ОЧЕНЬ ОПАСНАЯ, поскольку она делает ваши тесты ненадежными: некоторые тесты могут проходить, поскольку по умолчанию значение было возвращено методом stub, но функциональность не работает на реальном устройстве. Выключи.

+0

действительно, у меня есть эта опция включена! –

+0

@HuiWang, тогда вы обязательно должны отключить его, а затем подумайте о принятии ответа) – Vasiliy

+0

Большое спасибо за ваш ответ. Я очень ценю это. Другой вопрос: можно ли запустить тестовый тест без эмулятора? Это позволяет мне запускать тесты в CI –

2

Как описано в Building Local Unit Tests,

По умолчанию Android плагин для Gradle выполняет местный блок испытания против модифицированной версии android.jar библиотеки, которая не содержит любой фактический код.

Ваш тестовый код работает против раздели версии Bundle, который не содержит фактической реализации, следовательно, вы получите null всякий раз, когда вы пытаетесь получить что-то от него. Если вы действительно хотите проверить поведение Bundle, я бы предложил написать контрольно-измерительный тест, который запускается на устройстве Android против реальной реализации Bundle.

+0

Спасибо Егору, ваш ответ полезен, но Василий более совершенен. Спасибо :) –

+0

Действительно, это отличный ответ, рекомендуется! – Egor

Смежные вопросы