Issue
I am new to Mockito and I have a question. Let's say I try to have an object instance in my testing method. I know I can use @Mock
to have it and that's because we try to isolate the testing from that Object methods. However, to control the testing branch, I do need to set some values in this object. Should I still use Mock
or I should simply use new Object()
way to instantiate it? Or does it not matter (each way is fine)?
Thanks.
Solution
Let's find out, shall we?!
import org.mockito.Mockito;
class Scratch {
public final static String STATIC_CONST = "static const";
private final String JUST_CONST = "private const";
protected String protectedField = "protected field";
String packageProtectedField = null;
public static void main(String[] args) {
Scratch mocked = Mockito.mock(Scratch.class);
System.out.println("static = " + mocked.STATIC_CONST);
System.out.println("const = " + mocked.JUST_CONST);
System.out.println("protected = " + mocked.protectedField);
System.out.println("package = " + mocked.packageProtectedField);
mocked.packageProtectedField = "but now";
System.out.println("updated = " + mocked.packageProtectedField);
}
}
The above prints:
static = static const
const = private const
protected = null
package = null
updated = but now
Some thoughts:
Obviously, the static const
is really what you would expect (I used mocked.STATIC_CONST
to get the value, but hey, it is static, so the value doesn't come from mocked
but from the Scratch class definition anyway).
A bit surprising, at least for me is that assigning fields of a mocked object actually works. But please note: assignments in the original class are only effective for that final
field. In other words: Mockito gets that one right, but not for non-final fields.
Even more surprisingly, one can store values into the mock...
But honestly, nothing of that really matters. You see, in a sound design, all your mutable fields should be private in the very first place. That mutable state represents the absolute core of your objects. No outside code should ever deal with those! In other words: ideally, even your tests do not care about the internal state of your objects (in very rare situations, it might make sense to have a package protected getter method to access internal state for ease of verification, but that should be a rare exception).
Beyond that: when you mock an object, you absolutely should not be dealing in any ways with fields of that mock. You see: all the methods on that mock ... they have nothing to do with the original source code in your class. They are just that: empty shells that you can configure/verify using the corresponding Mockito methods. Let that sink in: the actual content of fields in a mocked object can't matter: because the methods that would normally deal with these fields ... "are not there"!
So, long story short: as shown, mocked objects can carry state. But as explained: you should ignore that aspect completely. The only correct way to use mocks is by specifying/verifying method calls on them.
Finally: I would expect that EasyMock, PowerMock(ito) behave in similar ways. On the other hand, I wouldn't be surprised either when other mocking frameworks actually behave slightly different. I only tested with Mockito because, imho, in 2018, Mockito is the one and only mocking framework one should be using when writing unit tests for the JVM.
Answered By - GhostCat
Answer Checked By - Dawn Plyler (JavaFixing Volunteer)