Тест Мокито в схеме MVP

Я пытаюсь провести модульное тестирование своего класса Presenter с использованием Mockito, и я всегда заканчиваю тем, что провалю тест:

org.mockito.exceptions.base.MockitoException: 
Cannot mock/spy class java.lang.String
Mockito cannot mock/spy following:
- final classes
- anonymous classes
- primitive types

Вот как выглядит мой класс Presenter:

public class EditorPresenter implements EditorContract.Presenter {

    private DataSource dataSourceImpl;
    private EditorContract.View mView;
    private SharedPreferences prefs;

    EditorPresenter(SharedPreferences prefs,
                    DataSourceImpl dataSourceImpl,
                    EditorContract.View mView) {
        this.dataSourceImpl = dataSourceImpl;
        this.mView = mView;
        this.prefs = prefs;

        mView.setPresenter(this);
    }

    @Override
    public void showNewNote() {
        String noteColor = prefs.getString("default_note_color", "#ef5350");
        String textColor = prefs.getString("default_text_color", "#000000");
        mView.noteColor(Color.parseColor(noteColor));
        mView.textColor(Color.parseColor(textColor));
     }
}

И это то, что я сделал до сих пор в классе EditorPresenterTest:

public class EditorPresenterTest {
    @Mock
    private EditorContract.View mView;
    @Mock
    private DataSourceImpl mDataSourceImpl;
    @Mock
    private SharedPreferences sharedPrefs;
    @Mock
    private String noteColor;
    @Mock
    private String textColor;

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

    @Test
    public void createEditorPresenter_newNote() {
        EditorPresenter editorPresenter = new EditorPresenter(
                sharedPrefs,
                mDataSourceImpl,
                mView);
         verify(mView).setPresenter(editorPresenter);
    }
    @Test
    public void showNewNote() {
        when(sharedPrefs.getString(eq("default_note_color"), eq("#ef5350"))).thenReturn(noteColor);
        when(sharedPrefs.getString(eq("default_text_color"), eq("#000000"))).thenReturn(textColor);
        verify(mView).textColor(Color.parseColor(noteColor));
        verify(mView).noteColor(Color.parseColor(textColor));
    }

(Примечание: я новичок в Mockito и тестировании) Я прошел createEditorPresenter_newNote() но showNewNote() провалил тест и показывает ошибку. Любые отзывы / ответы приветствуются. Надеюсь, кто-то мне поможет. Спасибо!

1 ответ

Решение

Сначала я отвечу на конкретный вопрос, который вы задали здесь, но имейте в виду, что у вас есть более крупная проблема, которая скрывается за вашей ошибкой компиляции, на которую я предоставлю ответ сразу после. (имейте в виду, что у меня нет реального опыта работы с Android, поэтому точные имена классов и варианты использования могут быть неверными, но ваши проблемы больше связаны с пониманием того, что делают тестовые среды, а не с синтаксически-ориентированной).

Ваша первая проблема заключается в том, что вы пытаетесь создать фиктивные типы класса String, что является окончательным. Как вы можете видеть в ошибке от Mockito:

Мокито не может издеваться над шпионом:

- выпускные занятия

По сути, нет реальной причины для создания макета String, потому что вы не тестируете функциональность String. Вы можете просто использовать константу. если это то, что вы хотите исправить, просто удалите @Mock аннотации от noteColor а также textColor переменные и инициализировать их с некоторыми постоянными значениями.


Подробнее о тестировании фреймворков и других проблемах, с которыми вы сталкиваетесь:

В вашем тестовом примере есть еще одна серьезная проблема: вы пытаетесь использовать EditorPresenter вы создали в первом тесте в рамках второго теста.

Дело в том, что тестовые фреймы запускают разные тесты в разных состояниях (справедливо). Поэтому, когда вы создаете EditorPresenter экземпляр внутри createEditorPresenter_newNote метод, он не будет виден вам в showNewNote Тестовый метод, потому что это другой процесс (не другой процесс ЦП - просто процесс в простом повседневном термине слова).


Что вы должны делать вместо этого?

Вот что before Метод предназначен для: он будет вызываться перед каждым запуском теста, поэтому вы можете настроить общую функциональность в одном месте.

то, что вы должны сделать, это больше на линии этого:

public class EditorPresenterTest {
    @Mock
    private EditorContract.View mView;
    @Mock
    private DataSourceImpl mDataSourceImpl;
    @Mock
    private SharedPreferences sharedPrefs;

    private EditorPresenter editorPresenter;

    @Before
    public void setUpEditorPresenter() {
        MockitoAnnotations.initMocks(this);
        this.editorPresenter = new EditorPresenter(
                sharedPrefs,
                mDataSourceImpl,
                mView);
    }

    @Test
    public void createEditorPresenter_newNote() {
         verify(mView).setPresenter(editorPresenter);
    }

    @Test
    public void showNewNote() {
        editorPresenter.showNewNote();
        String noteColor = "#ef5350"; // or whatever color you want
        String textColor = "#000000"; // or whatever color you want
        when(sharedPrefs.getString(eq("default_note_color"), eq("#ef5350"))).thenReturn(noteColor);
        when(sharedPrefs.getString(eq("default_text_color"), eq("#000000"))).thenReturn(textColor);
        verify(mView).textColor(Color.parseColor(noteColor));
        verify(mView).noteColor(Color.parseColor(textColor));
    }
}
Другие вопросы по тегам