Skip to content
Advertisement

Mockito only mock part of value and return real value for others

I have a unit test with a real object (Data data) and a boolean value (boolean required) as input.

mockTest(Data data, boolean required)

In my code I have

data.getObjectA().getPara1();

In other places I also have

data.getObjectA().getPara2();

And I’m trying to mock the return value of data.getObjectA().getPara1() to the booelan in the input

But below won’t work:

Mockito.when(data.getObjectA().getPara1()).thenReturn(required);

Or

Data dataSpy = Mockito.spy(data);
Mockito.when(dataSpy.getObjectA().getPara1()).thenReturn(required);
Mockito.when(dataSpy.getObjectA().getPara2()).thenCallRealMethod();

They either throw NullPointerException or Type errors

What is the correct way of mocking/spying it? I need to mock the return of para1 and keep para2 the real value.

Advertisement

Answer

If you want to override ObjectA’s behavior, then the instance that data returns needs to be a mock or spy. Fundamentally you have three choices:

Use a spy

As in Dawood’s answer:

Data dataMock = Mockito.mock(Data.class);
ClassA objectASpy = Mockito.spy(objectA);
when(dataMock.getObjectA()).thenReturn(objectASpy);
when(objectASpy.getPara1()).thenReturn(required);    // note 1

If you want getPara1() to return the same result for any internal calls within objectASpy, this is the way to go.

Use delegatesTo

This opts into a delegation-based behavior for Mockito, rather than overriding as it usually does.

Data dataMock = Mockito.mock(Data.class);
ClassA objectAMock = Mockito.mock(ObjectA.class, delegatesTo(objectA));
when(dataMock.getObjectA()).thenReturn(objectAMock);
when(objectASpy.getPara1()).thenReturn(required);    // note 1

If you only want getPara1() to return required on the outside calls, but have objectASpy return its original value for its internal calls, you could use this technique.

Use deep stubbing

Mockito does have a feature that would allow for your current syntax:

Mockito.when(dataSpy.getObjectA().getPara1()).thenReturn(required);
Mockito.when(dataSpy.getObjectA().getPara2()).thenCallRealMethod();

This feature is called returning deep stubs, and is best for when an object like dataSpy here represents a tree of very straightforward objects. That said, heed its warning:

WARNING: This feature should rarely be required for regular clean code! Leave it for legacy code. Mocking a mock to return a mock, to return a mock, (…), to return something meaningful hints at violation of Law of Demeter or mocking a value object (a well known anti-pattern).

Note 1

The line when(objectASpy.getPara1()).thenReturn(required); will actually call objectASpy.getPara1(). This might be fine as long as the object doesn’t throw an exception and doesn’t have side effects, but you can avoid that behavior with doVerb syntax so Mockito can see ahead of the call that you’re starting to stub.

Note that unlike when().thenReturn() syntax, the when below only contains the mock instead of the full mock method call.

doReturn(required).when(objectASpy).getPara1();
User contributions licensed under: CC BY-SA
8 People found this is helpful
Advertisement