MVP模式中的Mockito测试

时间:2018-12-16 05:14:52

标签: java android unit-testing mockito android-mvp

我试图使用Mockito对Presenter类进行单元测试,但我总是以失败告终:

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 个答案:

答案 0 :(得分:2)

我将首先回答您在此处提出的确切问题,但请记住,您还有一个更大的问题隐藏在编译错误的背后,稍后我将为您提供答案。 (请记住,我对Android没有真正的经验,因此确切的类名和用例可能无效,但是您的问题更多是在了解测试框架的功能而不是面向语法的情况下。)

第一个问题是您试图创建String类的模拟类型,这是最终的。正如您在Mockito的错误中看到的那样:

  

Mockito无法模拟/监视以下内容:

     

-期末课程

从本质上讲,没有真正的理由来创建String的模拟,因为您没有测试String功能。您可以只使用一个常数。  如果这是您要解决的问题,只需从@MocknoteColor变量中删除textColor批注,并使用一些恒定值对其进行初始化。


有关测试框架和您面临的其他问题的更多信息:

测试用例中还有另一个主要问题,那就是您试图在第二个测试的范围内使用在第一个测试中创建的EditorPresenter

问题是测试框架在单独的状态下运行不同的测试(正确地如此)。因此,当您在EditorPresenter方法内创建createEditorPresenter_newNote实例时,在showNewNote测试方法中您将看不到该实例,因为它是一个不同的进程(不是另一个CPU进程) -只是一个简单的日常用语过程。


您应该怎么做?

这就是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));
    }
}