【问题标题】:Asserting that Mockito mocked object gets set to null断言 Mockito 模拟对象设置为 null
【发布时间】:2016-11-29 20:14:19
【问题描述】:

我正在使用 Mockito 进行 JUnit 测试,但一直在找出一个断言问题。我正在创建一个模拟对象,然后使用模拟对象创建一个演示者对象。

@Mock
Object mFooBar;

private FooPresenter mFooPresenter;

@Before
public void setUp() throws Exception {
    MockitoAnnotations.initMocks(this);

    mFooPresenter = new FooPresenter(mFooBar);

}

在我的演示者的 onDestroy() 方法中,我将对象清空。

public FooPresenter(Object fooBar) {
    mFooBar = fooBar;
}

@Override
public void onDestroy() {
    mFooBar = null;
}

然后,当我尝试在我的 FooPresenterTest 中为 mFooBar 断言 Null 时,它失败了,因为它不为空。

@Test
public void testThatObjectsAreNullifiedInOnDestroy() throws Exception {
    fooPresenter.onDestroy();

    assertNull(mFooBar);
}

这失败了

Expected :<null>
Actual :mFooBar

那么我的问题是,与我为运行测试而实例化的对象相比,我的测试类中对模拟对象的引用是如何处理的?为什么 assertNull 应该设置为 null 却失败了?

【问题讨论】:

  • 嘿@kerseyd27,我假设您FooPresenter 中的mFooBar 字段是私有的,是否有任何属性暴露它?
  • 嘿@abest 是的,它是私有的,并且没有公开的属性。

标签: android junit mockito


【解决方案1】:

@kerseyd27,

从您的测试名称testThatObjectsAreNullifiedInOnDestroy 看来,您正在寻找验证注入的mFooBar 对象是否在演示者被销毁时被演示者释放。

首先,直接回答您的问题:

与我为运行测试而实例化的对象相比,我的测试类中对模拟对象的引用如何处理?

我会让这些答案(link 1link 2)自己说话,但请解释它与您的问题有何关系。模拟对象在 Test 类中实例化并按值传递到 FooPresenterFooPresenter.mFooBar 是一个单独的 引用(属于演示者),它指向模拟对象。在调用 onDestroy 方法之前,TestClass.mFooBarfooPresenter.mFooBar 引用同一个对象(模拟对象),但它们是对该对象的两个不同引用。

为什么 assertNull 应该设置为 null 却失败了?

您断言Test.mFooBar(属于测试类)为空。 Test.mFooBar 是在测试设置中创建的,但此变量永远不会设置为 null。另一方面,fooPresenter.mFooBar 变量 显式设置为 null。同样,虽然这些变量指向同一个对象,但引用本身并不相同。

如果您希望确保fooPresetner.mFooBar 为空,您可以将其设为本地包或使用属性公开它。仅出于测试目的这样做通常是不受欢迎的。

如果您希望确保在构造函数中对 mFooBar 对象执行某些操作,您可以编写如下测试:

public class TestClass {

    interface FooBar {
        void releaseSomething();
    }

    @Rule
    public MockitoRule r = MockitoJUnit.rule();

    @Mock
    FooBar mFooBar;

    @Test
    public void testThatObjectsAreNullifiedInOnDestroy() {
        new FooPresenter(mFooBar).onDestroy();
        verify(mFooBar).releaseSomething();
    }

    class FooPresenter {
        private FooBar mFooBar;

        public FooPresenter(FooBar fooBar) {this.mFooBar = fooBar;}

        @Override
        void onDestroy() {
            mFooBar.releaseSomething();
            mFooBar = null;
        }
    }
}

祝你好运,测试愉快!

【讨论】:

  • 这确实回答了我的具体问题。有了这些信息,我为我的案例所做的就是在调用 onDestroy 之后在我的类中的所有模拟对象上验证 NoMoreInterations;这样做是因为我同意出于测试目的进行诸如此类的编码更改是不受欢迎的。谢谢
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2018-11-01
  • 2016-03-16
  • 2013-11-24
  • 1970-01-01
  • 1970-01-01
  • 2013-04-21
  • 1970-01-01
相关资源
最近更新 更多