测试Android MVP演示者

时间:2018-10-10 23:10:32

标签: java android mvp

测试我的MVP演示者的最佳方法是什么?我已经阅读了大量的教程,每个教程都让我更加困惑。我刚刚开始学习测试,我认为从演示者开始会比较容易。

我的主持人

public class HymnPresenter implements HymnPresenterContract, HymnRepository.HymnsCallback{

    private HymnRepository hymnRepository;
    private HymnsViewContract hymnViewContract;

    public HymnPresenter() {
    }

    /*public HymnPresenter(HymnRepository repository, HymnsViewContract viewContract) {
        this.hymnViewContract = viewContract;
        this.hymnRepository = repository.attach(this);
    }*/



    @Override
    public void addHymns(ArrayList<Hymn> hymns){
        if(hymns != null && !hymns.isEmpty()) {
            hymnRepository.addHymns(hymns);
            hymnViewContract.showLoading();
        }else{
            handleError("Can not add null hymn");
        }
    }

    @Override
    public void addHymn(Hymn hymn){
        if(hymn != null) {
            hymnViewContract.showLoading();
            hymnRepository.addHymn(hymn);
        }else{
            handleError("Can not add null hymn");
        }
    }

    @Override
    public void handleSuccess() {
        hymnViewContract.success();
        hymnViewContract.hideLoading();
    }

    @Override
    public void handleError(String error) {
        hymnViewContract.error(error);
        hymnViewContract.hideLoading();
    }
} 

我的存储库 我正在使用Firebase Firestore数据库存储赞美诗

public class HymnRepository implements HymnPresenterContract{

    private HymnsCallback hymnsCallback;
    private CollectionReference collectionReference;
    private FirebaseFirestore db;

    public HymnRepository(FirebaseFirestore database, @HymnCollection CollectionReference collection) {
        this.db = database;
        this.collectionReference = collection;
    }

    public HymnRepository attach(@NonNull HymnsCallback callback){
        this.hymnsCallback = callback;
        return this;
    }

    @Override
    public void addHymns(ArrayList<Hymn> hymns){
        WriteBatch batch = db.batch();
        for(int i = 0; i < hymns.size(); i++){
            batch.set(collectionReference.document(), hymns.get(i));
        }
        batch.commit()
                .addOnSuccessListener(documentReference -> hymnsCallback.handleSuccess())
                .addOnFailureListener(e -> hymnsCallback.handleError(e.toString()));
    }

    @Override
    public void addHymn(Hymn hymn) {
        collectionReference.add(hymn)
                .addOnSuccessListener(documentReference -> hymnsCallback.handleSuccess())
                .addOnFailureListener(e -> hymnsCallback.handleError(e.toString()));
    }

    public interface HymnsCallback {
        void handleSuccess();
        void handleError(String error);
    }
}

我的主持人合同

public interface HymnPresenterContract {
    void addHymns(ArrayList<Hymn> hymns);
    void addHymn(Hymn hymn);
}

我的观看合同

public interface HymnsViewContract {
    void success();
    void error(String error);
}

因此,我设法使其正常工作。非常感谢大家……这就是我所做的。

@RunWith(MockitoJUnitRunner.Silent.class)
public class HymnPresenterTest {

    @InjectMocks
    public HymnPresenter hymnPresenter;
    @Mock
    public HymnRepository hymnRepository;
    @Mock
    public HymnsViewContract hymnsViewContract;
    @Mock
    private Hymn hymn;
    ArrayList<Hymn> hymns;

    @Before
    public void setUp() throws Exception {
        hymns = new ArrayList<>();
        hymns.add(hymn);
    }

    @Test
    public void addHymn_callsRepositoryAddHymn() throws Exception {
        hymnPresenter.addHymn(hymn);
        verify(hymnRepository).addHymn(eq(hymn));
    }

    @Test
    public void addHymns_callsRepositoryAddHymns() throws Exception {
        hymnPresenter.addHymns(hymns);
        verify(hymnRepository).addHymns(eq(hymns));
    }

    @Test
    public void addHymns_callsViewContractShowLoading() throws Exception {
        hymnPresenter.addHymns(hymns);
        verify(hymnsViewContract).showLoading();
    }

    @Test
    public void addHymn_callsViewContractShowLoading() throws Exception {
        hymnPresenter.addHymn(hymn);
        verify(hymnsViewContract).showLoading();
    }

    @Test
    public void addNullHymn_callsViewContractError() throws Exception {
        hymnPresenter.addHymn(null);
        verify(hymnsViewContract).error(anyString());
        verify(hymnsViewContract).hideLoading();
    }

    @Test
    public void addEmptyHymnList_callsViewContractError() throws Exception {
        ArrayList<Hymn> list = new ArrayList<>();
        hymnPresenter.addHymns(list);
        verify(hymnsViewContract).error(anyString());
        verify(hymnsViewContract).hideLoading();
    }


    @Test
    public void addNonNullHymn_callsViewContractSuccess() throws Exception {
        doAnswer(invocation -> {hymnPresenter.handleSuccess();
        return null;}).when(hymnRepository).addHymn(any(Hymn.class));

        hymnPresenter.addHymn(hymn);
        verify(hymnsViewContract).success();
        verify(hymnsViewContract).hideLoading();
    }
}

现在,当我取消对HymnPresenter构造函数的注释时,几乎所有测试都将失败。

java.lang.NullPointerException
    at com.ogotera.gusiihymnal.presenter.HymnPresenter.addHymn(HymnPresenter.java:43)
    at com.ogotera.gusiihymnal.presenter.HymnPresenterTest.addHymn_callsViewContractShowLoading(HymnPresenterTest.java:64)
    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.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:79)
    at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:85)
    at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
    at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:68)
    at com.intellij.rt.execution.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:51)
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:242)
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:70)
    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 com.intellij.rt.execution.application.AppMainV2.main(AppMainV2.java:131)

可能是什么问题?

1 个答案:

答案 0 :(得分:2)

我建议您研究Mockito,因为它是Android的模拟库。通过使用Contract模式让接口定义您的需求,您在代码结构上处在正确的轨道上。

然后,您可以设置JVM测试(在计算机和设备上运行的测试),以在其中测试演示者。

我建议通读此tutorial,以更好地了解如何测试代码。