Android, ошибка помещения при модульном тестировании с Robolectric - PullRequest
2 голосов
/ 17 марта 2020

Я пытаюсь создать несколько тестов для модели представления.

Модель представления включает в себя экземпляр базы данных, который вызывает базу данных

CallRoomDatabase db = CallRoomDatabase.getDatabase(application);

, где getDatabase принимает экземпляр Dao ()

  @Database(entities = {CallEntity.class}, version = 1)
 public abstract class CallRoomDatabase extends RoomDatabase {

public abstract CDao cDao();

// marking the instance as volatile to ensure atomic access to the variable
private static volatile CRoomDatabase INSTANCE;

public static CRoomDatabase getDatabase(final Context context) {
    if (INSTANCE == null) {
        synchronized (CallRoomDatabase.class) {
            if (INSTANCE == null) {
                INSTANCE = Room.databaseBuilder(context.getApplicationContext(),
                        CRoomDatabase.class, "database")
                        // Wipes and rebuilds instead of migrating if no Migration object.
                        // Migration is not part of this codelab.
                        .fallbackToDestructiveMigration()
                        .addCallback(sRoomDatabaseCallback)
                        .build();
            }
        }
    }
    return INSTANCE;
}

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

  java.lang.NullPointerException
at androidx.room.Room.getGeneratedImplementation(Room.java:79)
at androidx.room.RoomDatabase$Builder.build(RoomDatabase.java:952)
at com.s.o.dbutils.CRoomDatabase.getDatabase(CRoomDatabase.java:32)
at com.s.o.viewmodels.CViewModelTest.checkForNuTest(CViewModelTest.kt:66)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:27)
at org.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:83)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)

При RoomDatabase.java

            T db = Room.getGeneratedImplementation(mDatabaseClass, DB_IMPL_SUFFIX);

При Room.java klass is null

        static <T, C> T getGeneratedImplementation(Class<C> klass, String suffix) {

Я пытался вообще не использовать модель при тестировании, просто создаю экземпляр БД с помощью

          val db = CRoomDatabase.getDatabase(ApplicationProvider.getApplicationContext())

Все еще ломается в том же .build()

Есть идеи, как обойти это исключение?

На самом деле нам не нужно каким-то образом проверять БД, просто некоторые функции включены в эту модель, поэтому достаточно будет просто избежать ошибки.

Ответы [ 2 ]

2 голосов
/ 17 марта 2020

Комната должна быть проверена как Android Контрольно-измерительный прибор , а не тест JUnit.

Обновление:

Использование mockito для имитации базы данных и любых репозиториев.

Использование методов mockito, таких как:

  • @ Mock - аннотация для насмешки над глобальными и локальными переменными.
  • mock - Инициировать макет класса в строке.
  • когда - настроить поведение возврата для mock.
  • verify - Утверждать взаимодействия на макетах и ​​их методах.
  • times - Используется с verify для подтверждения количества вызовов к макету и его методу.
  • any - Сопоставление аргументов для утверждения предоставленных значений для mocks.

Использование примера Mockito. Я не знаю, как работает ваш код, я сделал несколько предположений, таких как существование Call.class и какие макеты вам потребуются:

@Mock private CallRoomDatabase database;
@Mock private CRoomDatabase cRoomDatabase;
@Mock private CDao cDao;

private MyClass myClass;

@Before 
public void setUp() {
    // initiate all globally defined mocks annotated with @Mock
    initMocks(this);

    // Setup our expected behaviour from the mock
    when(database.getDatabase()).thenReturn(cRoomDatabase);
    myClass = new myClass(database, cDao);
}

@Test 
public void givenSomeTest_whenCallingGetCall_thenInsertNewCall() {
    // Setup our expected behaviour from the mock
    when(cDao.getCall()).thenReturn(mock(Call.class));

    // do test

    // assert mock interaction with arguments and number of expected calls
    verify(cDao, times(1)).insertCall(any(mock(Call.class)))
}
0 голосов
/ 17 марта 2020

Для тестирования программы в отрыве от базы данных, я рекомендую реализовать 2 репозитория: 1 репозиторий для проекта, 1 для тестирования и общий интерфейс для них. Вы можете реализовать это с помощью Dagger 2.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...