如何告诉被测对象使用模拟而不是它自己的变量

How to tell the subject under test to use the mock instead of its own variable

我正在尝试测试 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's attemptLogin is called, but Mockito can only verify mocked objects' 方法,但我无法监视 LoginPresenter,因为它是最终的(由 AndroidAnnotations 生成)

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

最大的收获是:不要将对象创建逻辑与业务逻辑混合 这意味着不要在方法或构造函数中实例化对象(可能改用 DI),因为测试代码无权控制每当 SUT 的构造函数或方法被调用时链式反应开始,即绑定到 new关键字。

这意味着在我的例子中,LoginPresenter 不应该负责创建 LoginNetworkOperation 对象,而应该从外部获取它

这样我就可以告诉它使用模拟而不是具体实现,这样我就可以进行测试