Mockito's partial mocks. Testing real objects just got easier
In this article (in french), I wrote 6 months ago, I was searching for a mockito-like syntax to stub only one method of an object instance under test. Mockito brought it in it’s latest version.
Here is a recap of the need:
This is what I usually write to mock a method of a real object (usually to return a mock):
CopyFileRule rule = new CopyFileRule("src.txt", "dest.txt") {
@Override
protected FileTemplate createFileTemplate() {
return mock(FileTemplate.class);
}
};
This is clear enough but in real life, it tends to be more complex than in this example. Let’s say that CopyFileRule is Serializable, that createFileTemplate takes arguments that you’s like to check and that you use mockFileTemplate outside of CopyFileRule. Here is what the code would look like:
<strong>final</strong> FileTemplate mockFileTemplate = mock(FileTemplate.class);
CopyFileRule rule = new CopyFileRule("src.txt", "dest.txt") {
<strong>static final long serialVersionUID = ...</strong>; // Otherwise Eclipse will complain
@Override
protected FileTemplate createFileTemplate(String type) {
<strong>assertEquals("TYPE1", type);</strong>
return mockFileTemplate;
}
};
verify(mockFileTemplate).copy("src.txt", "dest.txt");
A little bit more confusing…
This is what I’d like to write:
CopyFileRule rule = intercept(new CopyFileRule("src.txt", "dest.txt"));
FileTemplate mockFileTemplate = mock(FileTemplate.class);
when(rule.createFileTemplate("TYPE1")).thenReturn(mockFileTemplate);
verify(mockFileTemplate).copy("src.txt", "dest.txt");
Simpler and keeps the given/when/then flow clear.
Mockito 1.8-rc1 introduces real partial mocks which are exactly that.
You create an object instance calling one of its constructors and you tell Mockito that you are willing to change some methods for this instance :
CopyFileRule rule = spy(new CopyFileRule("src.txt", "dest.txt"));
You replace a method:
when(rule.createFileTemplate()).thenReturn(mockFileTemplate);
Exactly the syntax I wanted! And it works for public AND protected methods, wether the method is called from the outside or the inside of the spied object.
Who said Mockito didn’t rule?
There is only one caveat to this syntax. The real rule.createFileTemplate() method will be called once. This can have a lot of side effects and might even fail throwing an exception (very often a NPE). To solve this, you can (should?) use this alternative Mockito syntax:
doReturn(mockFileTemplate).when(rule).createFileTemplate();
I like this syntax for partial mocks because it has no side effect and because it makes a difference between standard mocks and partial mocks.
A final warning: partial mocks should be used with caution. It’s powerful but can lead to poor design.
Shameless plug: Prototype based languages can do this natively. It might be the time to try Ioke