Don't understand how mocked classes works when invoking methods - java

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.

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

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.

Unit Test - Check a method call with an object that doesn't override equals

This is a general question on how to unit-test a Java Class using mock objects.
I can summarize my problem with this example. Let's say I've an Interface called MyInterface.java and a "TwoString" Object that doesn't override equals()
"TwoString.java"
private String string1;
private String string2;
public TwoString(String string1, String string2) {
this.string1 = string1;
this.string2 = string2;
}
...getters..setters..
"MyInterface.java"
void callMe(TwoString twoString);
Then I have "MyClass.java" Object. Its constructor accepts a concrete implementation of MyInterface.
MyClass methodToTest() contains the logic to create a TwoString oject in some way. Let's say that it will be created as
new TwoString("a","b")
So when methodToTest() is called it creates this TwoString object that will be passed to the Interface method callMe(TwoString twoString).
I basically want to mock the Interface. Create a MyClass object with this mock. Then verify that the mock method is called with a specific instance of TwoString.
I'm using EasyMock and this is some java code
"MyClassTest.java"
public void test() throws Exception {
MyInterface myInterfaceMock = createMock(MyInterface.class);
MyClass myClass = new MyClass(myInterfaceMock);
myInterfaceMock.callMe(new TwoString("a","b")); <--- fails here
expectLastCall();
replay(myInterfaceMock);
myClass.methodToTest();
verify(myInterfaceMock);
Here comes the problem. The TwoString object that I'm expecting in the call
myInterfaceMock.callMe(new TwoString("a","b"));
is different from the one generated in MyClass.methodToTest() because TwoString.java doesn't override equals.
I can skip the problem on the TwoString instance using
myInterfaceMock.callMe((TwoString)anyObject());
but I want to be sure that the interface method is called with a specific instance of TwoString that contains "a" as string1 and "b" as string2.
In this case the TwoString object is very simple and it will be easy to override the equals method - but what if I need to check a more complex object.
Thanks
edit:
I'll try to make it more readable with this example
public class MyClassTest {
private MyClass myClass;
private TaskExecutor taskExecutorMock;
#Before
public void setUp() throws Exception {
taskExecutorMock = createMock(TaskExecutor.class);
myClass = new MyClass(taskExecutorMock);
}
#Test
public void testRun() throws Exception {
List<MyObj> myObjList = new ArrayList<MyObj>();
myObjList.add(new MyObj("abc", referenceToSomethingElse));
taskExecutorMock.execute(new SomeTask(referenceToSomethingElse, ???new SomeObj("abc", referenceToSomethingElse, "whatever"))); <--- ??? = object created using data in myObjList
expectLastCall();
replay(taskExecutorMock);
myClass.run(myObjList);
verify(taskExecutorMock);
}
}
???SomeObj = object created by myClass.run() using data contained in myObjList.
Let's say that SomeObj comes from a third party library and it doesn't override equals.
I want to be sure that the taskExecutorMock.execute() method is getting called with a specific instance of that SomeObj
How can I test that the myClass.run() is actually calling the taskExecutorMock method with a correct instance
It is possible to use a custom equals matching method using org.easymock.IArgumentMatcher.
It should look something like:
private static <T extends TwoString> T eqTwoString(final TwoString twoString) {
reportMatcher(new IArgumentMatcher() {
/** Required to get nice output */
public void appendTo(StringBuffer buffer) {
buffer.append("eqTwoString(" + twoString.getString1() + "," + twoString.getString2() + ")");
}
/** Implement equals basically */
public boolean matches(Object object) {
if (object instanceof TwoString) {
TwoString other = (TwoString) object;
// Consider adding null checks below
return twoString.getString1().equals(object.getString1()) && twoString.getString2().equals(object.getString2());
}
else {
return false;
}
}
});
return null;
}
And is used as follows:
myInterfaceMock.callMe(eqTwoString(new TwoString("a","b")));
Some details may not be correct, but in essence it's how I've done it before. There is another example and more thorough explanations available in the EasyMock documentation. Just search for IArgumentMatcher.
First up - you probably mean "override equals" rather than implement, since all classes have some implementation of equals (the one they inherit from Object if they don't override anything else).
The answer in this case is simple - all value objects really really ought to implements equals and hashcode. Whether it's a simple one like TwoString, or the more complex object you allude to, it should be the object's responsibility to check whether it is equal to some other object.
The only other alternative would be to basically deconstruct the object in your test code - so instead of
assertEquals(expected, twoStr);
you'd do
assertEquals(expected.getStringOne(), twoStr.getStringOne());
assertEquals(expected.getStringTwo(), twoStr.getStringTwo());
Hopefully you can see that this is bad in at least three ways. Firstly, you're basically duplicating the logic that should be in the class' own equals() method; and anywhere that you want to compare these objects you'll have to write the same code.
Secondly, you can only see the object's public state, there could well be some private state that causes two apparently similar objects to be not equal (e.g. a Lift class could have a publically accessible "floor" attribute, but private "going up or down" state too).
Finally, it's a violation of the Law of Demeter for a third-party class to be basically messing about with the internals of TwoString trying to work out whether the things are equal.
The object itself should implement its own equals() method - pure and simple.
Take a look at Jakarta Commons Lang: EqualsBuilder.reflectionEquals()
While I agree with dtsazza that all value objects should have an equals() (and hashCode()) method, they're not always appropriate to testing: most value objects will base equality on a key, rather than on all fields.
At the same time, I'm leery of any test that wants to check all fields: it seems to me to be saying "make sure this method didn't change something that I wasn't planning for it to change." Which is a valid test, and on some level a very well-meaning test, but it's a little scary that you feel the need for it.
In this case the TwoString object is very simple and it will be easy to override the equals method - but what if I need to check a more complex object.
Once your objects start becoming so complex that you can't trivially check if they're equal from elsewhere, you should probably refactor and inject them as a dependency. This would change the design, but usually that's for the better.
You also seem to be relying on some knowledge of the internal behaviour of your classes. The above is an interaction test between two classes, which still sort of works, but the bigger your set of tested components gets, the less you can really still talk about "unit" tests. At a certain point you leave the realm of unit tests and you start doing integration tests, in which case you might be better off with a full blown test harness and isolating behaviour in certain places...
You can achieve this with argument captors in Mockito 1.8.
http://mockito.googlecode.com/svn/branches/1.8.0/javadoc/org/mockito/Mockito.html#15
I know you are using EasyMock but changing to Mockito is easy and it's much better!

Categories