Android 从MVP看仪器测试

Android 从MVP看仪器测试,android,mocking,mvp,android-espresso,android-testing,Android,Mocking,Mvp,Android Espresso,Android Testing,我正在开发一个具有MVP架构的Android应用程序,我已经能够测试Presenter和Model类,但现在我正在尝试测试View方法。 例如,我有以下观点: public interface SplashView extends BaseMVPView { void initPresenter(); void navigateToHome(); void onError(ApiError apiError); } 它是由一个活动实现的 public class

我正在开发一个具有MVP架构的Android应用程序,我已经能够测试Presenter和Model类,但现在我正在尝试测试View方法。 例如,我有以下观点:

public interface SplashView extends BaseMVPView {

    void initPresenter();

    void navigateToHome();

    void onError(ApiError apiError);
}
它是由一个活动实现的

public class SplashActivity extends BaseActivity implements SplashView {

    // MVP Presenter
    private SplashPresenter splashPresenter;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        initPresenter();
    }

    @Override
    public int getLayoutId() {
        return R.layout.activity_splash;
    }

    @Override
    public void destroy() {
        if(splashPresenter != null) {
            splashPresenter.onDestroy();
            splashPresenter = null;
        }
    }

    @Override
    public void initPresenter() {
        if(splashPresenter == null) {
            splashPresenter = new SplashPresenterImpl(this, ApiClient.getService());
            sync();
        }
    }

    @Override
    public void navigateToHome() {
        NavigationUtils.navigateToActivity(this, MainActivity.class, true);
    }

    @Override
    public void onError(ApiError apiError) {
        DialogUtils.showOKCancelDialog(...);
    }

    private void sync() {
        if(splashPresenter != null) {
            splashPresenter.sync();
        }
    }
}
如您所见,创建活动时,它初始化了presenter并调用一个方法,该方法将从API获取一些数据。API调用完成后,演示者将调用navigateToHome或OneError方法。所以我想对这两种情况都进行测试。我想这一定是一个仪器测试,但我不知道如何处理这种情况,以及如何调用这些方法


非常感谢

您可以为此使用mockito框架。verify执行您想要的操作-它检查是否调用了特定的方法


这是一篇文章,我希望它能有所帮助。

首先,我建议将您的MVP架构与一些Dagger对依赖注入的喜好混合起来,这对测试和模拟非常有帮助。您可以使用我在Github上发布的示例了解更多信息,该示例还包含不同类型的测试:

顺便说一句,在这种类型的开发中,您必须模拟您的SplashPresenter,并将其插入,而不是插入真实的演示者,以允许您使用模拟的演示者来更改真实的演示者,该演示者可以执行您想要的操作

为此,您必须扩展活动并覆盖initPresenter方法:

class MockSplashActivity extends SplashActivity {
    @Override
    public void initPresenter() {
        if (splashPresenter == null) {
            splashPresenter = new MockSplashPresenterImpl(this, ApiClient.getService());
            sync();
        }
    }
}
还可以扩展您的演示者,并更改您希望在测试中按照您希望的方式操作的方法(我认为您希望使用sync方法执行某些操作):


我希望它有帮助:)

视图不应该调用presenter上的任何管理方法,比如您的
sync()
,因为presenter管理视图,而不是相反。视图应该只传递给演示者它的操作,如单击或生命周期事件(如果需要)。将同步方法设为私有并在presenter内部调用,在您的案例中是在构造函数中,但我也建议不要手动创建presenter,使用factory或类似di的dagger,并使用名为
bindVIew(View-View)
的方法将视图连接到presenter。非常感谢,我正在从视图中调用演示者的sync方法,因为它必须在初始化时执行。我认为,如果视图执行该方法而不是presenter,那么它会比单击事件更好。您认为从视图中删除该部分更好吗?非常感谢是的,我想是的。Click事件是一个事件,但sync方法和我前面写的不同。所以在presenter中封装调用
sync
“谢谢,我会按照你说的进行更改。他的问题不在于如何验证调用方法,他想知道如何模拟presenter并将模拟实例注入片段或活动。非常感谢你的回答。”。我来看看你的github项目。一个问题,为什么Dragger 2会帮助我进行测试?我在使用Dragger 2时遇到了一些问题,我想我会使用它来将演示者注入视图,并将视图注入演示者,不是吗?那么,这对测试有什么影响呢?谢谢!我相信,如果你看看回购协议样本,你就会明白这一点;)你也可以看看这篇文章:非常感谢,我来看看!非常感谢你!当我面对同样的问题时,这消除了我的许多疑虑。
class MockSplashPresenterImpl extends SplashPresenterImpl {
    public MockSplashPresenterImpl(SplashActivity splashActivity, Object service) {
        super(splashActivity, service);
    }

    @Override
    public void sync() {
        splashActivity.doSomethingYouWant();
    }
}