How to mock a protected third party code method
Using Mockito I want to mock a property of a class so that I can check the output
public class MyClass extends ThirdPartyFramework {
Output goesHere;
@Override
protected setup(){
goesHere = new Output();
}
//...
}
public abstract class ThirdPartyFramework {
protected setup(){...}
//...
}
I need to inject the layout of the Output class so that I can verify that my code has written the correct output.
-
But I can't just
@InjectMock
because thesetup()
mid-runtime method is called and overwrites my injection. -
And I can't just make the setting public in
MyClass
, because the test code I'm running is shared and should work for all subclassesThirdPartyFramework
, so I only have a reference toThirdPartyFramework
what it meanssetup()
.
source to share
I decided to solve this by wrapping ThirdPartyFramework
and placing this class in the same package as the class ThirdPartyFramework
.
This way I could mock protected methods with Mockito. I was then able to use @InjectMock
to inject the layout of an object Output
and manage its method calls through that layout.
source to share
Are you tuned in to Mockito? I ask from the Mockito Frequently Asked Questions The Mockito FAQ states that it does not support mocking static methods, which I think you will need in this case to create your mock instead of the actual output.
I used PowerMock for a similar scenario:
whenNew(NewInstanceClass.class).withArguments(any()).thenReturn(mockObject);
which says that every time a NewInstanceClass is created, my mockObject is returned regardless of what constructor arguments were used and who created the NewInstanceClass at what time.
I also found the following example in the PowerMock docs:
PowerMock.expectNew(NewInstanceClass.class).andReturn(mockObject)
In fact, you can use it even if you are tied to Mockito, PowerMock contains helpers for Mockito to solve exactly this problem, which will allow you to use Mockito for all tests and PowerMock to mock constructs. Like this:
whenNew(Output.class).withNoArguments().thenReturn(yourOutputMock);
source to share
How about adding a setter for "goHere" and then set setup () and change goHere if its value is null. This way you can inject a value into testing that will not be overridden. Something like:
protected void setGoesHere( Output output ){
goesHere = output;
}
@Override
protected void setup(){
if(goesHere != null) goesHere = new Output();
}
Hope it helps.
source to share