如何告诉测试对象使用mock而不是自己的变量

时间:2016-03-22 09:12:22

标签: android unit-testing mocking mockito

我正在尝试测试LoginPresenter,我正在使用Mockito进行模拟。 Mockito不让我verify在SUT上进行方法调用,所以我必须模拟它的依赖关系,而verify已经LoginPresenter调用了它们的方法。

我遇到了以下情况:

LoginPresenter有一个名为attemptLogin的方法:

private void attemptLogin(String username, String password) {
    new LoginNetworkOperation(username, password).execute();
}

我必须模仿LoginNetworkOperation并使用Mockito,verify execute()上的方法调用。

@Test
public void testWhenUserNameAndPasswordAreEnteredShouldAttemptLogin() throws Exception {
    LoginView loginView = Mockito.mock(LoginView.class);
    LoginNetworkOperation loginNetworkOperation = Mockito.mock(LoginNetworkOperation.class);
    Mockito.when(loginView.getUserName()).thenReturn("George");
    Mockito.when(loginView.getPassword()).thenReturn("aaaaaa");
    loginPresenter.setLoginView(loginView);
    loginPresenter.onLoginClicked();
    Mockito.verify(loginNetworkOperation.execute());
}

但是,如何让LoginPresenter使用模拟的LoginNetworkOperation而不是它在attemptLogin方法中创建的那个?我需要更改LoginPresenter的设计以使用成员变量,并为它提供一个setter,这是次优的,因为方法中的局部变量很多,因为它只在那里使用。

我是否认为这件事错了?

最初,我想确认调用了LoginPresenter的{​​{1}},但Mockito只能验证模拟对象的方法,我无法监视attemptLogin,因为它是最终的(生成) LoginPresenter

1 个答案:

答案 0 :(得分:1)

我在这段视频中找到了答案: https://www.youtube.com/watch?v=wEhu57pih5w

最大的好处是:不要将对象创建逻辑与业务逻辑混合 这意味着不要在方法或构造函数中实例化对象(可能使用DI代替),因为只要调用SUT的构造函数或方法,测试代码就无法启动链式反应,它绑定到{{1} } keyword。

这意味着在我的情况下,new不应该负责创建LoginPresenter对象,而应该从外部获取

这样我就可以告诉它使用mock而不是具体的实现,因此,我将能够进行测试