2

Я использую ActiveAndroid для некоторых своих моделей, и я хотел начать модульное тестирование моей работы. К сожалению, я получаю массу ошибок, а именно, неспособность инициализировать ActiveAndroid, используя соответствующий контекст.Тестирование модуля ActiveAndroid с использованием Robolectric

ActiveAndroid является iniatilized:

ActiveAndroid.initialize (контекст)

Я попытался инициализировать контекст по:

  1. есть класс заглушки, расширяющий приложение и использовать его для инициализировать db.

    private class TestApp extends com.activeandroid.app.Application{ 
        @Override 
        public void onCreate() { 
        super.onCreate(); 
        initialiseDB(getDatabaseName()); 
        } 
    
        protected String getDatabaseName() { 
        return "sad"; 
        } 
    
        private void initialiseDB(String dbName) { 
         ActiveAndroid.initialize(this); 
        } 
    } 
    

Это не удается, так как обратный класс нуль для .getPackageName() и .getApplicationContext(), оба из которых используется внутри Initialize.

Я также пытался использовать ShadowContextWrapper, но я могу использовать его неправильно. Вот как я пошел об этом:

ShadowContextWrapper shadowContextWrapper = new ShadowContextWrapper(); 
    shadowContextWrapper.setApplicationName("appName"); 
    shadowContextWrapper.setPackageName("package"); 
    Context context = shadowContextWrapper.getApplicationContext(); 

Этот подход не с NPE в ShadowContextWrapper.java:52 который часть Robolectric. Сама линия:

Context applicationContext = this.realContextWrapper.getBaseContext().getApplicationContext(); 

Я использую AS 1.2, robolectric3.0 и activeandroid 3.1.

Вот пример теста, который я запускаю.

@RunWith(CustomRobolectricTestRunner.class) 
    public class ItemTest { 

    public void setUp(){ 

    } 

    @Test 
    public void checkJUnitWork() { 
     assertThat(true, is(true)); 
    } 

    @Test 
    public void testSave(){ 
     Item item = new Item("name", "units", 5.0, 4.5, 10.0); 
     assertThat(item.getName(),is("name")); 
    } 

    public void tearDown(){ 

    } 
} 

Мой заказ Runner выглядит следующим образом:

public class CustomRobolectricTestRunner extends RobolectricTestRunner { 

public CustomRobolectricTestRunner(Class<?> testClass) 
     throws InitializationError { 
    super(testClass); 
    String buildVariant = (BuildConfig.FLAVOR.isEmpty() 
      ? "" : BuildConfig.FLAVOR+ "/") + BuildConfig.BUILD_TYPE; 
    String intermediatesPath = BuildConfig.class.getResource("") 
      .toString().replace("file:", ""); 
    intermediatesPath = intermediatesPath 
      .substring(0, intermediatesPath.indexOf("/classes")); 

    System.setProperty("android.package", 
      BuildConfig.APPLICATION_ID); 
    System.setProperty("android.manifest", 
      intermediatesPath + "/manifests/full/" 
        + buildVariant + "/AndroidManifest.xml"); 
    System.setProperty("android.resources", 
      intermediatesPath + "/res/" + buildVariant); 
    System.setProperty("android.assets", 
      intermediatesPath + "/assets/" + buildVariant); 

    ShadowContextWrapper shadowContextWrapper = new ShadowContextWrapper(); 
    shadowContextWrapper.setApplicationName("appName"); 
    shadowContextWrapper.setPackageName("package"); 
    Context context = shadowContextWrapper.getApplicationContext(); 

    ActiveAndroid.initialize(context); 

} 

}

+0

Поскольку это модульное тестирование, я бы удалил ActiveRecord из тестов вообще –

+1

Не могли бы вы также добавить в свой тестовый код и файл манифеста, который вы используете для своих тестов? У меня есть тайное подозрение, что может возникнуть нечто странное в том, как Robolectric создает приложение – abest

+0

@EugenMartynov Эй. Я думал об этом. Но у меня есть своя бизнес-логика для моих моделей, которую я бы хотел проверить. Кроме того, я хотел бы выполнить некоторую работу с базами данных, например, установить данные об оборудовании и проверить ее. Таким образом, мне действительно нужно, чтобы это работало. –

ответ

4

Итак, проблема у вас возникли с вашими тестами, что TestApp не работает. Чтобы запустить его, вам нужно настроить тест на использование манифеста, который указывает TestApp как приложение для запуска.

Настройте свой TestApp следующим образом: /test каталог вашего исходного дерева ... например. /src/test/java/some-long-package/TestApp.java:

package com.some.company; 

public class TestApp extends Application { 
    @Override 
    public void onCreate() { 
     super.onCreate(); 
     ActiveAndroid.initialize(this); 
    } 
} 

Это важная часть

Создать андроид файл манифеста в /test дерева источника. Попросите этот файл манифеста указать TestApp в качестве приложения. Таким образом, создать манифест на пути, как /src/test/resources/TestManifest.xml, содержащий следующее:

<manifest xmlns:android="http://schemas.android.com/apk/res/android" 
    package="com.android.test"> 

     <application android:name="com.some.company.TestApp"> 

    </application> 
</manifest> 

Я бы рекомендовал избавиться от CustomRobolectricTestRunner, как по умолчанию Robolectric тест 3,0 бегун на будет делать большую часть того, что вам нужно сделать. Если вам нужно протестировать различные варианты сборки, используйте @RunWith(RobolectricGradleTestRunner.class).

Но сейчас, настройка тесты следующим образом:

@RunWith(RobolectricTestRunner.class) 
@Config(constants = BuildConfig.class, manifest = "src/test/resources/TestManifest.xml", sdk = Build.VERSION_CODES.LOLLIPOP) 
public class MainAppTest { 

    @Test 
    public void runtimeApplicationShouldBeTestApp() throws Exception { 
     String actualName = RuntimeEnvironment.application.getClass().getName(); 
     String expectedName = TestApp.class.getName(); 
     assert(actualName).equals(expectedName); 
    } 
} 

Это @Config(manifest= ...) битой установки Robolectric использовать тест манифест и тестовое приложение. Тест выше простого подтверждает, что контекст приложения, используемый в тесте, действительно равен TestApp.class . Это обеспечит правильную инициализацию ActiveAndroid для теста.

Я также согласен с Eugen, что вы, возможно, пытаетесь сделать немного в своих тестах. Проверяя свою БД через приложение, вы фактически создаете тест интеграции. Я бы рекомендовал как можно больше раскрыть функциональность.

Счастливые испытания!

+0

Спасибо. Это хорошо меня поддержало на правильном пути к выяснению моей проблемы. Что касается тестов, то, как работает AA, конструктор DataModels не будет работать без db. Таким образом, инициализация завершилась неудачей даже без тестирования CRUD. Еще раз спасибо. –

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