【问题标题】:How to tell the subject under test to use the mock instead of its own variable如何告诉被测对象使用模拟而不是自己的变量
【发布时间】:2016-07-09 02:17:48
【问题描述】:

我正在尝试测试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,这是次优的,因为方法中的局部变量很多,因为它只在那里使用。

我在这整件事上做错了吗?

最初,我想验证 LoginPresenterattemptLogin 是否被调用,但 Mockito 只能验证模拟对象的方法,我无法监视 LoginPresenter,因为它是最终的(由 AndroidAnnotations 生成)

【问题讨论】:

标签: android unit-testing mocking mockito


【解决方案1】:

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-01-02
    • 1970-01-01
    • 2023-03-18
    • 2012-10-27
    • 2017-05-18
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多