我正在尝试测试LoginPresenter
,并且我正在使用Mockito进行模拟。Mockito不允许我在SUT上verify
方法调用,所以我必须模拟它的依赖项,并且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
使用模拟的登录网络操作,而不是它在attemptLogin
方法中创建的操作?我需要更改 LoginPresenter 的设计以使用成员变量,并为其提供一个资源库,这是次优的,因为方法中的局部变量很多,因为它只在那里使用。
我把整件事做错了吗?
最初,我想验证是否调用了LoginPresenter
的attemptLogin
,但 Mockito 只能验证模拟对象的方法,我无法监视LoginPresenter
因为它是最终的(由 AndroidAnnotations
生成)
我在这个视频中找到了答案:https://www.youtube.com/watch?v=wEhu57pih5w
最大的收获是:不要将对象创建逻辑与业务逻辑混为一谈这意味着不要实例化方法或构造函数中的对象(可能改用 DI),因为每当调用 SUT 的构造函数或绑定到 new
关键字时,测试代码就无法控制链式反应启动。
这意味着在我的情况下,LoginPresenter
不应该负责创建LoginNetworkOperation
对象,而应该从外部获取它。
这样我就可以告诉它使用模拟而不是具体的实现,因此,我将能够进行测试