1

I am using Mockito to do JUnit tests, and stuck figuring out an assertion issue. I'm creating a mock object, and then creating a presenter object using the mocked object.

@Mock
Object mFooBar;

private FooPresenter mFooPresenter;

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

    mFooPresenter = new FooPresenter(mFooBar);

}

In the onDestroy() method in my presenter, I null out the object.

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

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

Then when I try to assertNull for mFooBar in my FooPresenterTest, it fails because it is not null.

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

    assertNull(mFooBar);
}

This fails as

Expected :<null>
Actual :mFooBar

My questions then are, how are the references handled to the mocked objects in my test class compared to the object I instantiated to run the test? Why does assertNull fail when it should have been set to null?

kerseyd27
  • 158
  • 1
  • 9
  • Hey @kerseyd27, I'm assuming the the `mFooBar` field in your `FooPresenter` is private, is there any property exposing it? – abest Nov 29 '16 at 20:56
  • Hey @abest Yes it is private, and there are no exposing properties for it. – kerseyd27 Nov 29 '16 at 21:21

1 Answers1

1

@kerseyd27,

From your test name testThatObjectsAreNullifiedInOnDestroy it appears that you're looking to verify that injected mFooBar object is released by your presenter when the presenter is destroyed.

First, to directly answer your questions:

how are the references handled to the mocked objects in my test class compared to the object I instantiated to run the test?

I'll let these answers(link 1, link 2) speak for themselves, but explain how it pertains to your issue. The mocked object is instantiated in the Test class and passed by value into the FooPresenter. The FooPresenter.mFooBar is a separate reference(belonging to the presenter) that points to the mocked object. Until the onDestroy method is called, TestClass.mFooBar and fooPresenter.mFooBar reference the same object(the mock object), but they are two distinct references to this object.

Why does assertNull fail when it should have been set to null?

You are asserting the Test.mFooBar(belonging to the Test class) is null. Test.mFooBar is created by in the test setup, but this variable is never set to null. On the other hand, the fooPresenter.mFooBar variable is explicitly set to null. Again, while these variables point to the same object, the references themselves are not the same.

If you're looking to ensure that the fooPresetner.mFooBar is null, you could make it package-local or expose it with a property. Doing this just for test purposes is generally frowned upon.

If you're looking to ensure that some action is performed on the mFooBar object in the constructor, you could write a test like the following:

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;
        }
    }
}

Good Luck & Happy Testing!

Community
  • 1
  • 1
abest
  • 724
  • 6
  • 16
  • 1
    This did answer my specific question. With this information, what I did for my case was to verifyNoMoreInterations on all of the mocked objects in my class after onDestroy is called; this was done because I agree that making coding changes such as this for test purposes is frowned upon. Thanks – kerseyd27 Dec 08 '16 at 15:16