Testing a void method with Mockito - java

I have a method like this:
public void someMethod() {
A a = new A(); // Where A is some class.
a.setVar1(20);
a.someMethod();
}
I want to test 2 things:
The value of Var1 member variable of a is 20.
someMethod() is called exactly once.
I have 2 questions:
Are those test objectives correct or should I be testing something else ?
How exactly do I test this using Mockito ?

You can't test that using Mockito, because Mockito can't access a local variable that your code creates and then let go out of scope.
You could test the method if A was a injected dependency of your class under test, or of the method under test
public class MyClass {
private A a;
public MyClass(A a) {
this.a = a;
}
public void someMethod() {
a.setVar1(20);
a.someMethod();
}
}
In that case, you could create a mock A, then create an instance of MyClass with this mock A, call the method and verify if the mock A has been called.
With your code, as it is, the only way to test the code is to verify the side effects of calling someMethod() on an A with var1 equal to 20. If A.setVar1() and A.someMethod() don't have any side-effect, then the code is useless: it creates an object, modifies it, and forgets about it.

Use JB Nizet's advice but note that order is important to you:
When verifying and order is important, use:
A mock = mock(A);
new MyClass(mock).someMethod();
InOrder order = inOrder(mock);
order.verify(mock).setVar1(20);
order.verify(mock).someMethod();
(Testing for exactly one invocation is the default in mockito).
Caution
This kind of test will be tightly coupled to the implementation. So do this in moderation. In general aim for testing state rather than implementation where possible.

Ad 1) Testing setters usually doesn't make much sense, but if you want to to then surely you have a getter on A to verify that var1 is set to 20?
Ad 2) You can use #Spy and verify() to test invocations on methods.
A spy = spy( a );
verify( spy , times( 1 ) ).someMethod();
Your example code is a bit terse, so my answer is very general - hope you can work with it.
Cheers,

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

Mock parent final method

I want to mock a subclass method which is inherited.This method cannot be overriden since it's final.When using "when ,thenReturn " mockito is calling the real method which causes some exceptions and I want to avoid that.
class A{
final String doSomething()
{
//Some treatement
return "";
}
}
class B extends A{
//
}
class TestB {
#Test
public void test(){}
B b=mock(B.class);
when(B.doSomething()).thenReturn("");// it fails because it calls //the real method of A
}
}
There are two reasons why could be asking this questions:
a) you are dealing with some kind of 3rd party library/design that you can't change; but that you somehow want to test. In that case using PowerMock can be an option, as PowerMock manipulates byte code and makes it possible to mock final methods/classes. But: PowerMock is famous for creating all kinds of weird problems; and seriously: you are much better of not using it.
b) you are getting "unit testing" wrong: you never create a mock object of class B in order to test something on class B. You only mock objects X, Y, Z that your code in B needs to do something.
So, your real problem is: you have some method "doSomethingElse()" on B that you want to test. And "doSomethingElse()" calls "doSomething()" ... and your test fails because you can't control the behavior of "doSomething()". There are two options to get out of that problem:
1) Do you really need inheritance? Must B really extend A, or would it be better if a B object ... simply owned an A object? (if so, you can mock that A object and gain control over its methods). Ever heard about CoI?
2) You reverse dependencies; like in:
abstract class A {
final void doSomething() { doSomethingSpecific() ... }
abstract void doSomethingSpecific();
}
class B extends A { #Override void doSomethingSpecific() { ...
resulting in a "proper OO" solution to your "testing" problem.
Besides: if "doSomething()" is final on class A, then that should be in order to achieve OCP: you define some behavior on A that subclasses can use (or use indirectly) and that should not change. So, you can turn back to your design, and maybe that final was added "for the wrong reason", then it might be fine to simply remove the keyword.

How to mock a method call without actually calling its submethods

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

Count method invocation of method variable instance

I have some code like this:
class FooBar {
private String stateFoo;
public FooBar(String stateFoo){
this.stateFoo = stateFoo;
}
public void foo() {
FooInst f = FooInstFactory.createSomeFooInst(AnotherStaticFooConfig.getSomePath);
f.justCountMe();
}
}
My goal is to make sure that f.justCountMe() was executed exactly once. I know how to do it in general with mockito.
What I don't know is how do I inject a mocked version of FooInst into the foo method? So that I can count the invocation?
Is it even possible to do so?
You need to use powermockito and mock static method. See explanation how to do this here
PowerMockito mock single static method and return object
If possible; I suggest to avoid using mocking libraries that temper with static fields (in the way PowerMock/Mockito do) - as it often comes with undesired side effects (for example many "coverage" tools produce invalid results when static mocking takes places).
So my suggestion: re-design your class under test. Instead of fetching f from a static factory; provide a constructor for either the factory or f; then you can mock the corresponding object; without the need to turn to the mighty but dangerous "Powerxyz" stuff.

How to mock a single method in java

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().

Categories