Reputation: 53
How to call a method of a method of a mocked class?
when(mockedClass.method1().method2()).thenReturn(x);
This line of code is throwing
org.mockito.exceptions.misusing.MissingMethodInvocationException
I am not able to call the 2nd method after mocking the class.
I tried doReturn
, spy but didn't work.
Any solution is appreciated!
Upvotes: 2
Views: 1428
Reputation: 26330
method2()
does not belong to the type you mocked. It belongs to the type that is returned by method1()
. You can only tell the mock what to return on calls to method1()
(that's the reason for the misusing
part in the exceptions package name).
In theory, you the create a mock for the type returned by method1()
and instruct mockedClass
to return that second mock and then tell the new mock to return x
when method2()
is called. But letting mocks return other mocks is usually a really bad idea for a multitude of reasons.
Without knowing your actual code and what you really want to achieve, it is really hard to give any advice on this. Therefore I can only offer some general hints, which might or might not apply to you situation.
Usually, object1.method1().method2()
call chain should be avoided. The "Tell, don't ask" principle says, that asking an object for something and then operating on that something should be avoided (Tell an object what to do, instead of asking it for things and do it yourself). The call chain implies that method1()
is returning another object (object2
) which is then used to call method2()
. Instead of this, you should add a method to object1
which is doing the call to method2()
and returns its result. Simple example:
This is what you classes might look like
public class C1 {
private C2 o2;
public C2 method1() {
return o2;
}
}
public class C2 {
public int method2() {
return computeValue();
}
}
// somewhere else:
int value = object1.method1().method2();
Instead, you could design it like this:
public class C1 {
private C2 o2;
//public C2 method1() {
// return o2;
//}
public int method3() {
return o2.method2();
}
}
public class C2 {
public int method2() {
return computeValue();
}
}
// somewhere else:
//int value = object1.method1().method2();
int value = object1.method3();
This way you avoid the call chain and C1
does not have to reveal that it contains a value of type C2
which means you could change that without the callers being aware of it.
Apart from the better design and the avoidance of the call chain (also called a "train wreck"), this allows you to do the following for your mocking situation:
//when(mockedClass.method1().method2()).thenReturn(x);
when(mockedClass.method3()).thenReturn(x);
Upvotes: 2