I want to mock a concrete class in a TestNG test case. The class could look like this (simplified example):
public class Example() {
private MyHello myHello;
public Example(MyHello myHello) {
this.myHello = myHello;
}
public String doSomething() {
return myHello.doSomethingElse();
}
}
Now we want to mock Example return some defined value:
#BeforeMethod
public void setUp() {
this.example = mock(Example.class);
when(this.example.doSomething()).thenReturn("dummyValue");
}
This looks quite good but in fact it isn't. The last line in the setup method calls the method on an instance of Example, this instance didn't get an MyHello through the constructor and so I get a NPE in the setUp method.
Is there a way to either inject an MyHello while creating the mock or to disallow Mockito calling the method on a real instance?
Edit
The issue, that caused the observed behaviour was, that the doSomething() method is actually final. I overlooked that when I tried to solve that issue. And this is a known limitation with mockito anyway. So I'll either remove the finals or extract an interface for that class.
See if using doReturn("dummy").when(example).doSomething() does the trick.
Mockito.doReturn
From JavaDoc:
Use doReturn() in those rare occasions when you cannot use when(Object).
Beware that when(Object) is always recommended for stubbing because it is argument type-safe and more readable (especially when stubbing consecutive calls).
Here are those rare occasions when doReturn() comes handy:
When spying real objects and calling real methods on a spy brings side effects
List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing:
doReturn("foo").when(spy).get(0);
You can benefit from spy keyword instead of mock.
As far as I'm concerned from the documentation of Mockito, you are able to make partial mock with spy.
For detailed explanation you can benefit from subject 13 in the doc of it.
Related
I am aware of duplicate, bo no answer about actual question was given there.
How to verify if method is called on System under test (not a mock)
I have a class:
class A {
public long a() {
if(something) {
return quicklyCalculatedResult
} else {
return b() run on separate thread, with this one blocked
}
}
public long b() {} //doStuffOnCurrentThread;
}
I have a complete set of tests for b(), which does the heavy lifting. Unfortunately I have to make an ugly think like a() (legacy code) and I don't want to copy all the tests. Of method b(). Also, both of these need to be public.
I want to verify that under certain circumstances a() calls b(), but I cannot do that, beacause tested class is not a mock. I need a way to verify that method was called on a real object, not only a mock.
Mockito and other kotlin mocking libraries provide partial mocking or similar functionality. You can specify real methods to be called, while the other methods remain stubs:
Mockito java example:
A classUnderTest = mock(A.class);
when(classUnderTest.a()).thenCallRealMethod();
classUnderTest.a();
verify(classUnderTest).b()
See the mockito Documentation on partial mocking. Partial mocking is not encouraged because it does not fit good OOP design, but in your case it fit its intended purpose, which is to test difficult legacy code.
Kotlin example with vanilla Mockito:
val classUnderTest = mock(A::class.java)
`when`(classUnderTest.a()).thenCallRealMethod()
classUnderTest.a()
verify(classUnderTest).b()
mockito-kotlin provides extensions that allow you to use mockito in a more kotlin idiomatic way. Unfortunately there does not appear to be a way to do partial mocking in a kotlin idiomatic way, but it can be achieved in mockito-kotlin like so:
val classUnderTest = mock<A>()
doCallRealMethod().whenever(classUnderTest).a()
classUnderTest.a()
verify(classUnderTest).b()
MockK, an idiomatic kotlin mocking library, allows for this functionality with spys. After creating a spy of the class you can choose to stub methods:
val classUnderTest = spyk<A>()
every { classUnderTest.b() } returns 1L
classUnderTest.a()
verify { classUnderTest.b() }
You can make A a spy with #Spy or Mockito.spy(). This will allow you to invoke and test a() method logic but also replace b() with an invariant. This can be illustrated with a list:
List list = new LinkedList();
List spy = Mockito.spy(list);
// Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
// You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
I have been unable to find a way to use "Deep Stubs" for stubbing methods on a spy in Mockito. What I'm looking to do is something like this:
#Spy private Person person = //retrieve person
#Test
public void testStubbed() {
doReturn("Neil").when(person).getName().getFirstName();
assertEquals("Neil", person.getName().getFirstName());
}
The code above compiles with no issues, but upon running the test, it fails saying that the return type (the Name class, in this case) cannot be returned by getName().
Normally, when mocking, you have to use
#Mock(answer = Answers.RETURNS_DEEP_STUBS) for each mocked object. However, spy does not seem to have anything like this.
Has anyone ever successfully done deep stubbed mocking using a spy?
The error I'm receiving is listed below:
String cannot be returned by getName()
getName() should return Name
Due to the nature of the syntax above problem might occur because of:
1. Multithreaded testing
//I'm not doing multithreaded testing
2. A spy is stubbed using when(spy.foo()).then() syntax. It is safer to stub spies with doReturn|Throw() family of methods
//As shown above, I'm already using the doReturn family of methods.
While I'd still like to know if there's a better way to do this, I'd like to post a solution for anyone who comes looking.
The solution below works fine, by requiring you to create a new mock (or even a real object/spy) for each level of your dependencies. In other words, instead of chaining your method calls to create your stub, you mock each level individually.
#Spy private Person person = //retrieve person
#Mock private Name name;
#Test
public void testStubbed() {
doReturn(name).when(person).getName();
doReturn("Neil").when(name).getName();
assertEquals("Neil", person.getName().getFirstName());
}
You can get a little closer to the deep stubs you want by using doAnswer(RETURNS_DEEP_STUBS), but you can't override arbitrarily-deep method calls without taking care to stub their parent calls. I'd stick to manual single-level-deep mocks as you do in your answer, or use even less mocking if possible.
A spy's default behavior is to delegate to its real method call, which will typically return a real object (like your Name) and not a Mockito spy. This means that you won't normally be able to change those objects' behavior using Mockito: a spy isn't really the same class as the object being spied on, but rather is a generated subclass where every field value is copied from the spied-on value. (The copying is an important feature, because a delegating spy would have very unintutitive behavior regarding this, including for method calls and field values.)
Foo foo = new Foo();
foo.intValue = 42;
foo.someObject= new SomeObject();
Foo fooSpy = Mockito.spy(foo);
// Now fooSpy.intValue is 42, fooSpy.someObject refers to the exact same
// SomeObject instance, and all of fooSpy's non-final methods are overridden to
// delegate to Mockito's behavior. Importantly, SomeObject is not a spy, and
// Mockito cannot override its behavior!
So this won't work:
doReturn("Neil").when(person).getName().getFirstName();
// Mockito thinks this call ^^^^^^^^^ should return "Neil".
And neither will this:
doReturn("Neil").when(person.getName()).getFirstName();
// The object here ^^^^^^^^^^^^^^^^ won't be a mock, and even if Mockito
// could automatically make it a mock, it's not clear whether that
// should be the same spy instance every time or a new one every time.
In your situation, I'd choose the following, in order from most preferable to least:
Create a real Name object and install it using doReturn. It looks like Name is a data object (aka value object) after all, which likely means it has no dependencies, solid behavior, and difficult-to-mock state transitions. You may not be gaining anything by mocking it.
Create a mock Name and install it as you do in your answer. This is particularly useful if Name is more complicated than it looks to be, or if it doesn't actually exist in the first place.
Replace getName to return a deep stub...
doAnswer(RETURNS_DEEP_STUBS).when(person).getName();
...which you can then override...
doReturn("Neil").when(person.getName()).getFirstName();
...even for arbitrarily deep values.
doReturn("Gaelic").when(person.getName()
.getEtymology()
.getFirstNameEtymology())
.getOrigin();
As a final editorial, one of the hazards of partial mocks is that it makes it really hard to tell which behavior is real and which is faked; this might make it hard for you to guarantee that the behavior you're testing is prod behavior and not mock behavior. Another hazard of deep stubbing is that you may be violating the Law of Demeter by definition. If you find yourself using this kind of technique often in tests, it may be time to consider rearchitecting your system under test.
#Test
public void listTypeTest() throws Exception {
doCallRealMethod().when(listType).setRecordCount(new BigInteger("556756756756"));
listType.setRecordCount(new BigInteger("556756756756"));
doCallRealMethod().when(listType).getRecordCount();
assertEquals(new BigInteger("556756756756"), listType.getRecordCount());
}
I need to use a third party class in Mockito.when as parameter. The class does not have equals implementation and hence Mockito.when always returns null except the case where any() is used.
The below always returns null:
when(obj.process(new ThirdParytClass())).thenReturn(someObj);
however, this works
when(obj.process(any(ThirdParytClass.class))).thenReturn(someObj);
But, the problem is the process() method is called twice in the actual code and the use of any() is ambiguous and does not help in covering the multiple scenarios to test.
Extending the class does not help and also leads to other complications.
Is there a way to address the issue.
If a class doesn't implement a (sensible) equals(Object), you can always match instances yourself by implementing your own ArgumentMatcher. Java 8's functional interfaces make this pretty easy to write (not that it was such a big hardship in earlier versions, but still):
when(obj.process(argThat(tpc -> someLogic()))).thenReturn(someObj);
More often than not, however, if you just want to compare the class' data members, the built-in refEq matcher would do the trick:
ThirdParytClass expected = new ThirdParytClass();
// set the expected properties of expected
when(obj.process(refEq(expected))).thenReturn(someObj);
Mockito provides the captor feature that may help you to bypass limitations of equals() method because overriding equals() to make a test pass may be desirable but it is not always the case.
And besides, sometimes, equals() may not be overridable. It is your use case.
Here is a example code with an ArgumentCaptor :
#Mock
MyMockedClass myMock;
#Captor
ArgumentCaptor argCaptor;
#Test
public void yourTest() {
ThirdPartyClass myArgToPass = new ThirdPartyClass();
// call the object under test
...
//
Mockito.verify(myMock).process(argCaptor.capture());
// assert the value of the captor argument is the expected onoe
assertEquals(myArgToPass , argCaptor.getValue());
}
I started using JUnits (Mockito) from yesterday. I searched for similar question, but didn't find.
I have a class with method method1() which in turn calls method2().
I don't want to mock method2
I am mocking call to method1(). I was expecting that it would return the custom object(without going ahead and calling method2) which I want. But instead it proceeds and tries to call method2().
class A {
method1() {
//do something.
method2();
}
}
I mocked method1 and return any object (say new Integer(1)).
I dont want method2 to be called. but when I am debugging this Junit. It goes and calls method2. Hence fails.
When using syntax like this:
#Test public void yourTest() {
A mockA = Mockito.mock(A.class, Mockito.CALLS_REAL_METHODS);
when(mockA.method1()).thenReturn(Integer.valueOf(1));
}
then the first thing Java will do is to evaluate when(mockA.method1()), which requires calling mockA.method1() to get a value to pass into when. You don't notice this with other mocks, because Mockito mocks return nice default values, but with spies and CALLS_REAL_METHODS mocks this is a much bigger problem. Clearly, this syntax won't work.
Instead, use the methods beginning with do:
#Test public void yourTest() {
A mockA = Mockito.mock(A.class, Mockito.CALLS_REAL_METHODS);
doReturn(Integer.valueOf(1)).when(mockA).method1();
}
As part of .when(mockA), Mockito will instead return an instance that has no behavior, so the call to method1() never happens on a real instance. do syntax also works with void methods, which makes it more flexible than when(...).thenReturn(...) syntax. Some developers advocate for using doReturn all the time; I prefer thenReturn because it's slightly easier to read, and can also do return type checking for you.
As a side note, prefer Integer.valueOf(1) over new Integer(1) unless you absolutely need a brand new instance. Java keeps a cache of small integers, and this can be faster than allocating a brand new reference if you need to manually box an int into an Integer.
Usually you mock interfaces or abstract classes and provide implementations of abstract methods. In your case you want to substitute the real implementation of a concrete class. This can be achieved via partial mocks.
http://docs.mockito.googlecode.com/hg/org/mockito/Mockito.html#16
Is it possible to Mock a single method of a Java class?
For example:
class A {
long method1();
String method2();
int method3();
}
// in some other class
class B {
void someMethod(A a) {
// how would I mock A.method1(...) such that a.method1() returns a value of my
// choosing;
// whilst leaving a.method2() and a.method3() untouched.
}
}
Use Mockito's spy mechanism:
A a = new A();
A aSpy = Mockito.spy(a);
Mockito.when(aSpy.method1()).thenReturn(5l);
The use of a spy calls the default behavior of the wrapped object for any method that is not stubbed.
Mockito.spy()/#Spy
Use the spy() method from Mockito, and mock your method like this:
import static org.mockito.Mockito.*;
...
A a = spy(new A());
when(a.method1()).thenReturn(10L);
Based on Mockito's documentation the accepted answer is not the correct way to Spy real objects.
The right way to do this is to use the following pattern:
doReturn("foo").when(spy).get(0);
Below you can find the snippet from Mockito's about Spying on real objects.
Important gotcha on spying real objects!
Sometimes it's impossible or
impractical to use when(Object) for stubbing spies. Therefore when
using spies please consider doReturn|Answer|Throw() family of methods
for stubbing. Example:
List list = new LinkedList();
List spy = spy(list);
//Impossible: real method is called so spy.get(0) throws IndexOutOfBoundsException (the list is yet empty)
when(spy.get(0)).thenReturn("foo");
//You have to use doReturn() for stubbing
doReturn("foo").when(spy).get(0);
Mockito does not delegate calls
to the passed real instance, instead it actually creates a copy of it.
So if you keep the real instance and interact with it, don't expect
the spied to be aware of those interaction and their effect on real
instance state. The corollary is that when an unstubbed method is
called on the spy but not on the real instance, you won't see any
effects on the real instance. Watch out for final methods. Mockito
doesn't mock final methods so the bottom line is: when you spy on real
objects + you try to stub a final method = trouble. Also you won't be
able to verify those method as well.
Assuming you are using jmockit:
public void testCase(#Mocked("methodToBeMocked") final ClassBoBeMocked mockedInstance) {
new Expectations() {{
mockedInstance.methodToBeMocked(someParameter); returns(whateverYouLikeItToReturn);
}}
mockedInstance.callSomemethod();
}
You could simply create a subclass of A that overrides method1().