How to mock a method call without actually calling its submethods - java

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

Related

How to verify with Mockito that another public method of SUT was called during test

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);

Equivalent of Answers.RETURNS_DEEP_STUBS for a spy in mockito

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());
}

mockito "verify" checks current state, but does not reset mock invocations

I'm using Mockito in my JUnit tests. The test is an integration test, testing a whole scenario, thus there are many assertions and verify(mock)s in it.
My problem is, that I'm writing some production code, doing some assertions and then verify the mock which works, until there is an identical mock invocation. see the simplified code:
interface I {
void m1();
void m2();
}
// some decorator
class T implements I {
public T(I decorated) {
/*...*/
}
/* ... */
}
public void testInvalid() {
I m = mock(I.class);
T t = new T(m);
t.m1();
assertEquals("m1", t.getLastMethod());
verify(m).m1();
t.m2();
assertEquals("m2", t.getLastMethod());
verify(m).m2();
t.m1();
assertEquals("m1", t.getLastMethod());
verify(m).m1();
// TooManyActualInvocations t.m1(): Wanted 1 time, but was 2 times ...
}
public void testValid() {
I m = mock(I.class);
T t = new T(m);
t.m1();
assertEquals("m1", t.getLastMethod());
t.m2();
assertEquals("m2", t.getLastMethod());
t.m1();
assertEquals("m1", t.getLastMethod());
verify(m, times(2)).m1();
verify(m).m2();
}
One idea is to verify the mocks at the end, but let's say there is a small stupid implementation mistake which leads to invoking the method m1 twice and m2 once but not as I would expect it in testInvalid but in the end the test would pass. I want my test to fail early. How do I accomplish that?
Thank you.
Thanks to #Woozy Coder:
Didn't mentioned, that reset would also be an option, but since it has to be called between verify and the next equal stub call, it makes it hard to write "nice" and correct tests, I think. There should be two different mocking styles:
"postcondition" mocking as Mockito does it
"early" mocking which would be an implicit reset after a verify-block
something like:
earlyReset(m).after(
new Runnable() {
t.someMethodInvokingTwoStubs();
verify(m).someMethod1();
verify(m).someMethod2();
}
);
I am having a similar problem and decided to use clearInvocations() (arrived in Mockito 2.1)
https://javadoc.io/static/org.mockito/mockito-core/3.3.3/org/mockito/Mockito.html#clearInvocations-T...-
Using reset() has the drawback that you loose your stubbing as well, clearInvocations() only clears the invocations.
Mockito was written to avoid brittleness, such that verification can make the least-specific assertion possible to allow for implementations to evolve without changing the test. If it doesn't matter to your test system that you're calling these methods multiple times, then you shouldn't ask Mockito to check it.
Alternatives:
Use atLeast or atLeastOnce to ensure the call happened at all without worrying how many additional times the method is called.
If the call is stubbed to have return values, infer that the system works from state assertions about the data you've stubbed.
If you really need stub or verification behavior to change across a single test method, your mock may grow outside the scope of what Mockito does well. Use an Answer for a single method, or write a manual Fake that simulates the interconnected methods properly.

Don't understand how mocked classes works when invoking methods

I have a class that have one getter like this:
public Animal get(int id) {
final Animal animal = crudRepository.get(id);
assetRepository.attachAssets(animal);
return animal;
}
I want to create a simple unit test for this. I have mocked the crudRepository to always return a fixed animal. I have also mocked the assetRepository and set the mocked repository on the class that I want to test. However, I don't understand how it works, why don't I get nullpointers and errors when invoking the attachAssets method? It is has return type void. I mean, in the attachAssets method I use things that I never created (sessions etc.). Does Mockito automatically catch exceptions or something, is it something special for void methods or what? In other words, I haven't stubbed the attachAssets method of the assetRepository so why don't it fail (or should it even fail, I don't know)?
A mock is a dummy implementation. It's a subclass of the mocked class which overrides all its methods, and replace their implementation with alomst nothing (i.e. it returns what you tell it to return, throws what you tell it to throw, and records the invocations to be able to verify them after).
Here's some example class:
public class AssetRepository {
public void attachAssets(Animal a) {
// some real implementation
}
}
And here's a simplified example of a mock implementation created by Mockito:
public class MockAssetRepository extends AssetRepository {
private List<Invocation> invocations = new ArrayList<>();
#Override
public void attachAssets(Animal a) {
// store the invocation to be able to chack if it has been called,
// how many times, etc.
invocations.add(new Invocation("attachAssets", a);
}
}
You see that whatever your implementation is, it's not called, because attachAssets() is overridden in the mock.
if you mock the AssetRepository the methods are called on the mock and the actual implementation doesn't matter anymore. Instead Mockito uses a dummy version of the method (which does nothing).
The default behaviour for Mockito if you haven't told it anything else is to do nothing or return null/0, whichever is appropriate. It will usually only throw an exception if you tell it to. Other mocking frameworks might complain if you call some unexpected methods.

How to init a mock of a real class

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.

Categories