Ошибка насмешки Класс, который содержит ссылку на SQLiteOpenHelper

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

Вот мой простой тест:

public class AddressPresenterTest {
    @Mock
    private AddressView mView;

    @Mock
    private AddressDataSource mDataSource;

    @Mock
    private AddressLocalDataSource mLocalDataSource;

    @Captor
    ArgumentCaptor<DataSourceCallback<Province>> mProvinceCallbackCaptor;

    private AddressPresenter mPresenter;

    @Before
    public void beforeTest() {
        MockitoAnnotations.initMocks(this);

        mPresenter = new AddressPresenter(mDataSource, mView);
        mPresenter.setLocalDataSource(mLocalDataSource);
    }

    @Test
    public void When_SelectProvince_DataIsNull_ShowErrorMessage() {
        mPresenter.getLocalProvinceById(2129023);

        // Cause data source has callback, we need to capture the callback
        ArgumentCaptor<Integer> provinceIdCaptor = ArgumentCaptor.forClass(Integer.class);
        verify(mLocalDataSource).fetchProvinceById(provinceIdCaptor.capture(), mProvinceCallbackCaptor.capture());
        mProvinceCallbackCaptor.getValue().onFailedLoad();

        verify(mView).loadContentError();
    }
}

Когда я запускаю этот тест, я получил ошибку,

org.mockito.exceptions.base.MockitoException: 
Mockito cannot mock this class: class com.dai.uangteman.data.AddressLocalDataSource.

Mockito can only mock non-private & non-final classes.
If you're not sure why you're getting this error, please report to the mailing list.

Java               : 1.8
JVM vendor name    : Oracle Corporation
JVM vendor version : 25.77-b03
JVM name           : Java HotSpot(TM) 64-Bit Server VM
JVM version        : 1.8.0_77-b03
JVM info           : mixed mode
OS name            : Mac OS X
OS version         : 10.12.6

Underlying exception : java.lang.IllegalArgumentException: Could not create type

    at com.dai.uangteman.view.fragment.presenter.AddressPresenterTest.beforeTest(AddressPresenterTest.java:41)
...
Caused by: java.lang.IllegalArgumentException: Could not create type
    at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:140)
    ... 28 more
Caused by: java.lang.NoClassDefFoundError: android/database/sqlite/SQLiteOpenHelper
    at java.lang.ClassLoader.defineClass1(Native Method)
    at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:142)
    at net.bytebuddy.TypeCache.findOrInsert(TypeCache.java:138)
    ... 45 more
Caused by: java.lang.ClassNotFoundException: android.database.sqlite.SQLiteOpenHelper
    at java.net.URLClassLoader.findClass(URLClassLoader.java:381)
    ... 87 more

Когда я обойти, чтобы изменить свой AddressLocalDataSource класс, я нашел что-то странное.

public class AddressLocalDataSource {
    private StaticDatabaseHelper mDatabaseHelper;

//    /**
//     * @param mDatabaseHelper
//     */
//    public AddressLocalDataSource(StaticDatabaseHelper mDatabaseHelper) {
//        this.mDatabaseHelper = mDatabaseHelper;
//    }

    public void setDatabaseHelper(StaticDatabaseHelper mDatabaseHelper) {
        this.mDatabaseHelper = mDatabaseHelper;
    }
    ...
}

Ниже того, что я нашел:

  1. Я пытаюсь удалить мой конструктор и метод установки, который содержит StaticDatabaseHelper параметр объекта и все работает!
  2. Я пытаюсь изменить StaticDatabaseHelper инициализация в методе установки это не работает!

Проблема моя AddressLocalDataSource нужен экземпляр StaticDatabaseHelper учебный класс.

Любая идея? благодарю вас

2 ответа

Решение

✔ Ответить

Через пару часов я ищу решение и получаю самое простое решение. Я думаю, что есть некоторые неполные в библиотеке Android для тестирования. Поэтому я просто запускаю команду gradle для очистки:

./gradlew clean test

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

public class AddressPresenterTest {

    @Mock
    private AddressView mView;

    @Mock
    private AddressDataSource mDataSource;

    @Mock
    private AddressLocalDataSource mLocalDataSource;

    @Captor
    ArgumentCaptor<DataSourceCallback<Province>> mProvinceCallbackCaptor;

    private AddressPresenter mPresenter;

    @Before
    public void beforeTest() throws Exception {
        MockitoAnnotations.initMocks(this);

        mPresenter = new AddressPresenter(mDataSource, mView);
        mPresenter.setLocalDataSource(mLocalDataSource);
    }

    @Test
    public void When_SelectProvince_DataIsNull_ShowErrorMessage() {
        mPresenter.getLocalProvinceById(2129023);

        // Cause data source has callback, we need to capture the callback
        ArgumentCaptor<Integer> provinceIdCaptor = ArgumentCaptor.forClass(Integer.class);
        verify(mLocalDataSource).fetchProvinceById(provinceIdCaptor.capture(), mProvinceCallbackCaptor.capture());
        mProvinceCallbackCaptor.getValue().onFailedLoad();

        verify(mView).loadContentError();
    }
}

Надеюсь, это поможет, спасибо

Кажется, вам также нужно смоделировать StaticDatabaseHelper. Затем Mockito должен автоматически вставить ваш смоделированный экземпляр в AddressLocalDataSource. Поэтому добавление следующей строки может решить вашу проблему:

public class AddressPresenterTest {
    @Mock
    StaticDatabaseHelper mockedDatabaseHelper;
    ...

В моем случае в моем проекте используется javassist-3.11.0.GA.jar. После того, как Google опубликовал некоторые статьи о вышеупомянутой проблеме, связанной с версией javassist, я пытаюсь обновить javassist до javassist-3.18.2-GA.jar или javassist-3.21.0-GA.jar, проблема решена.

Некоторые другие проблемы могут быть решены следующим образом:

java.lang.VerifyError: Несогласованные кадры стека в целевой ветви 40 Исключение

,

java.lang.RuntimeException: java.io.IOException: недопустимый тип константы: 18

,

Основное исключение: java.lang.IllegalArgumentException: не удалось создать тип

С Уважением,

Другие вопросы по тегам