Тест Mockito в шаблоне 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() не прошел тест и показывает ошибку. Любые отзывы/ответы приветствуются. Надеюсь, мне кто-нибудь поможет. Спасибо!


person AJ Seraspi    schedule 16.12.2018    source источник


Ответы (1)


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

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

Mockito не может издеваться/шпионить следующее:

- заключительные занятия

По сути, нет никакой реальной причины для создания макета строки, потому что вы не тестируете функциональность строки. Вы можете просто использовать константу. если это то, что вы хотите исправить, просто удалите аннотации @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));
    }
}
person Chaos Monkey    schedule 16.12.2018
comment
Как я могу протестировать метод showNewNote()? Я хочу проверить, запущены ли методы просмотра - person AJ Seraspi; 16.12.2018
comment
@AJSeraspi обновил мой комментарий, надеюсь, он поможет, и вы примете это как правильный ответ. - person Chaos Monkey; 16.12.2018