I'm using Mockito in some tests.
I have the following classes:
class BaseService {
public void save() {...}
}
public Childservice extends BaseService {
public void save(){
//some code
super.save();
}
}
I want to mock only the second call (super.save) of ChildService. The first call must call the real method. Is there a way to do that?
If you really don't have a choice for refactoring you can mock/stub everything in the super method call e.g.
class BaseService {
public void validate(){
fail(" I must not be called");
}
public void save(){
//Save method of super will still be called.
validate();
}
}
class ChildService extends BaseService{
public void load(){}
public void save(){
super.save();
load();
}
}
#Test
public void testSave() {
ChildService classToTest = Mockito.spy(new ChildService());
// Prevent/stub logic in super.save()
Mockito.doNothing().when((BaseService)classToTest).validate();
// When
classToTest.save();
// Then
verify(classToTest).load();
}
No, Mockito does not support this.
This might not be the answer you're looking for, but what you're seeing is a symptom of not applying the design principle:
Favor composition over inheritance
If you extract a strategy instead of extending a super class the problem is gone.
If however you are not allowed to change the code, but you must test it anyway, and in this awkward way, there is still hope. With some AOP tools (for example AspectJ) you can weave code into the super class method and avoid its execution entirely (yuck). This doesn't work if you're using proxies, you have to use bytecode modification (either load time weaving or compile time weaving). There are be mocking frameworks that support this type of trick as well, like PowerMock and PowerMockito.
I suggest you go for the refactoring, but if that is not an option you're in for some serious hacking fun.
Consider refactoring the code from ChildService.save() method to different method and test that new method instead of testing ChildService.save(), this way you will avoid unnecessary call to super method.
Example:
class BaseService {
public void save() {...}
}
public Childservice extends BaseService {
public void save(){
newMethod();
super.save();
}
public void newMethod(){
//some codes
}
}
I found a way to suppress the superclass method using PowerMockito. 3 simple steps need for this
Use PowerMockito.suppress method and MemberMatcher.methodsDeclaredIn method to supress parent class method
Second add Parent class in #PrepareForTest
Run your test class with PowerMock ie add #RunWith(PowerMockRunner.class) above your test class.
#RunWith(PowerMockRunner.class)
#PrepareForTest({BaseService.class})
public class TestChildService(){
#Spy
private ChildService testChildServiceObj = Mockito.spy(new ChildService());
#Test
public void testSave(){
PowerMockito.suppress(MemberMatcher.methodsDeclaredIn(BaseService.class));
//your further test code
testChildServiceObj.save();
}
}
Note: This will work only when the superclass method does not return anything.
Maybe the easiest option if inheritance makes sense is to create a new method (package private??) to call the super (lets call it superFindall), spy the real instance and then mock the superFindAll() method in the way you wanted to mock the parent class one. It's not the perfect solution in terms of coverage and visibility but it should do the job and it's easy to apply.
public Childservice extends BaseService {
public void save(){
//some code
superSave();
}
void superSave(){
super.save();
}
}
create a package protected (assumes test class in same package) method in the sub class that calls the super class method and then call that method in your overridden sub class method. you can then set expectations on this method in your test through the use of the spy pattern. not pretty but certainly better than having to deal with all the expectation setting for the super method in your test
Even if i totally agree with iwein response (
favor composition over inheritance
), i admit there are some times inheritance seems just natural, and i don't feel breaking or refactor it just for the sake of a unit test.
So, my suggestion :
/**
* BaseService is now an asbtract class encapsulating
* some common logic callable by child implementations
*/
abstract class BaseService {
protected void commonSave() {
// Put your common work here
}
abstract void save();
}
public ChildService extends BaseService {
public void save() {
// Put your child specific work here
// ...
this.commonSave();
}
}
And then, in the unit test :
ChildService childSrv = Mockito.mock(ChildService.class, Mockito.CALLS_REAL_METHODS);
Mockito.doAnswer(new Answer<Void>() {
#Override
public Boolean answer(InvocationOnMock invocation)
throws Throwable {
// Put your mocked behavior of BaseService.commonSave() here
return null;
}
}).when(childSrv).commonSave();
childSrv.save();
Mockito.verify(childSrv, Mockito.times(1)).commonSave();
// Put any other assertions to check child specific work is done
You can do this with PowerMockito and replace behavior only of the parent class method with continuing testing the child's class method. Even when the method is returning some value, lets say a string, you can do something like this:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ BaseService.class })
public class TestChildService() {
private BasicService basicServiceObj;
private ChildService testee;
#Before
public void init() throws Exception {
testee = new ChildService();
basicServiceObj = PowerMockito.spy(new BaseService());
PowerMockito.doReturn("Result").when(basicServiceObj, "save", ... optionalArgs);
}
#Test
public void testSave(){
testee.save();
}
}
If you are returning nothing (void) then instead of doReturn you can use doNothing. Add some optionalArgs if the method have some arguments, if not, then skip that part.
The reason is your base class is not public-ed, then Mockito cannot intercept it due to visibility, if you change base class as public, or #Override in sub class (as public), then Mockito can mock it correctly.
public class BaseService{
public boolean foo(){
return true;
}
}
public ChildService extends BaseService{
}
#Test
#Mock ChildService childService;
public void testSave() {
Mockito.when(childService.foo()).thenReturn(false);
// When
assertFalse(childService.foo());
}
There is simple approach that works for most of cases. You can spy your object and stub the method you want to mock.
Here is an example:
MyClass myObjectSpy = Mockito.spy(myObject);
org.mockito.Mockito.doReturn("yourReturnValue").when(mySpyObject).methodToMock(any()..);
So, when you test your object, you can use myObjectSpy and when methodToMock is called, it will overwrite the normal behavior by a mock method.
This code for a method with return. In case you have a void method you can use doNothing instead.
Trying to use Mockito's spy function for my JUnit test. I originally had a Class:
public class App1 {
public String method1() {
sayHello();
}
public sayHello() {
Systems.out.println("Hello");
}
}
Everything in my test class was working correctly with mockito spy on above class:
#Test(expected = IOException.class)
public void testMethod1Failure(){
App1 a1 = spy(App1);
doThrow(IOException.class).when(a1).sayHello();
a1.method1();
}
But after that i had to switch things around and take sayHello() method into another class to be used as static method:
public class App1 {
public String method1() {
App2.sayHello();
}
}
public class App2 {
public static void sayHello() {
Systems.out.println("Hello");
}
}
After this change, my original JUnit testcase is broken and i am unsure how i can use Mockito spy to start App1 that calls the external App2 static method... does anyone know how i can do it? Thanks in advance
Mockito does not support mocking static code. Here are some ways to handle it:
Use PowerMockito or similar framework as suggested here: Mocking static methods with Mockito.
Refactor your code converting static method back to an instance method. As you've found static methods are not easy to Unit test.
If it's inexpensive to execute actual static method in question then just call it.
I have a library I am trying to mock for testing... There is a Java 8 interface with a static method implementation like this:
public interface Router {
public static Router router(Object param) {
return new RouterImpl(param);
}
}
And I am trying to mock that returned value:
PowerMockito.mockStatic(Router.class);
PowerMockito.doReturn(mockRouter).when(Router.router(any()));
But when I run the tests through a debugger, the mock instance is not returned.
I've tried a number of different permutations of the static mocking, but I cannot get the static method to return my mock value. Any thoughts?
You are doing it right, but we will have to wait when mocking static interface method is implemented/fixed in PowerMock. Watch this pull request:
https://github.com/jayway/powermock/issues/510
Note: Good news is that issue in Javassist is already fixed:
https://github.com/jboss-javassist/javassist/pull/11
Why not wrap it in an abstraction that you can mock?
class RouterFactory {
Router createRouter(Object param) {
return Router.router(param);
}
}
And use it in your class
class YourClass {
private final RouterFactory routerFactory;
YourClass(RouterFactory routerFactory) {
this.routerFactory = routerFactory;
}
void doSth() {
// do sth
}
}
Then you can mock the RouterFactory without any problems and you don't have to use Powermock.
I have a class FileGenerator, and I'm writing a test for the generateFile() method that should do the following:
1) it should call the static method getBlockImpl(FileTypeEnum) on BlockAbstractFactory
2) it should populate variable blockList from the subclass method getBlocks()
3) it should call a static method createFile from a final helper class FileHelper passing a String parameter
4) it should call the run method of each BlockController in the blockList
So far, I have this empty method:
public class FileGenerator {
// private fields with Getters and Setters
public void generateBlocks() {
}
}
I am using JUnit, Mockito to mock objects and I've tried using PowerMockito to mock static and final classes (which Mockito doesn't do).
My problem is: my first test (calling method getBlockList() from BlockAbstractFactory) is passing, even though there is no implementation in generateBlocks(). I have implemented the static method in BlockAbstractFactory (returning null, so far), to avoid Eclipse syntax errors.
How can I test if the static method is called within fileGerator.generateBlocks()?
Here's my Test Class, so far:
#RunWith(PowerMockRunner.class)
public class testFileGenerator {
FileGenerator fileGenerator = new FileGenerator();
#Test
public void shouldCallGetBlockList() {
fileGenerator.setFileType(FileTypeEnum.SPED_FISCAL);
fileGenerator.generateBlocks();
PowerMockito.mockStatic(BlockAbstractFactory.class);
PowerMockito.verifyStatic();
BlockAbstractFactory.getBlockImpl(fileGenerator.getFileType());
}
}
I have no experience with PowerMock, but since you didn't get an answer yet I'm just been reading through the documentation to see if I can help you a bit on your way.
I found that you need to prepare PowerMock so that I knows which static methods it needs to prepare to be mocked. Like so:
#RunWith(PowerMockRunner.class)
#PrepareForTest(BlockAbstractFactory.class) // <<=== Like that
public class testFileGenerator {
// rest of you class
}
Here you can find more information.
Does that help?
Working example:
#RunWith(PowerMockRunner.class)
#PrepareForTest({ClassStaticA.class, ClassStaticB.class})
public class ClassStaticMethodsTest {
#Test
public void testMockStaticMethod() {
PowerMock.mockStatic(ClassStaticA.class);
EasyMock.expect(ClassStaticA.getMessageStaticMethod()).andReturn("mocked message");
PowerMock.replay(ClassStaticA.class);
assertEquals("mocked message", ClassStaticA.getMessageStaticMethod());
}
mockito-version: 1.9.0
I want to setup a call to a method of a mocked object in mockito without calling the original method itself:
EDIT: this example actually works as expect, i.e. the body method "test()" of does not get executed. However, after further investigation I noticed that the original method had the default visibility modifier and I suspect this to cause problems since after changing it to public (shouldn't this be the same?!) it works as expected.
e.g.
public class TestClass {
public String test() {
System.out.println("test called!");
return "test";
}
}
//in test
TestClass mock = mock(TestClass.class);
when(mock.test()).thenReturn("mock!"); //<-- prints test called here? why? how can I switch it off?
The following, running under Mockito 1.9.0 and JUnit 4.8.2, does not print anything to my console:
import static org.mockito.Mockito.*;
import org.junit.Test;
public class TestNonCall {
public class TestClass {
public String test() {
System.out.println("test called!");
return "test";
}
}
#Test
public void doTest() {
final TestClass mock = mock(TestClass.class);
when(mock.test()).thenReturn("mock!");
}
}
Further, if I put a breakpoint in the test() method it is never hit.
Perhaps post more code? It looks like your example is not complex enough to demonstrate the behaviour you're having problems with.
Also: are you using the latest version of Mockito?
Edit: New Thought: Are You Mocking a Final Method?
If you add a final modifier to the method you are mocking, you get the behaviour you reported.
This is because Mockito does not mock final and static methods. Instead, it delegates the calls to the real implementation.
Might your actual code be attempting to mock a final method?
If so, you can use PowerMock, which is an extension to Mockito that allows mocking final methods.
You would need to add the following annotations to your test case class:
#RunWith(PowerMockRunner.class)
#PrepareForTest(TestClass.class)
public class TestNonCall {
// ...
}
and mock the class using the PowerMock method in your test method:
final TestClass mock = PowerMockito.mock(TestClass.class);
then proceed as usual.