jueves, julio 26, 2012

Answering with Mockito




Overwhelmed by industry, Searching for a modern day savior from another place, Inclined toward charity (The Answer - Bad Religion)

When you are writing unit tests, you must keep in mind to not have dependencies to external components. To avoid this we use mock frameworks which for me the easiest one to use is Mockito.

In this post we are going to see an "advanced" technique used in Mockito to return same argument instance on a mocked method using Answer interface.

Suppose we are writing unit tests for class which manages Person and Job classes and as operation it uses a DAO class for inserting the relationship class (M:N) between Person and Job called PersonJob.

For example class under test will look something like:


So in this case it seems obvious that you need to mock personJobDao.

Let's create the mock and record the interaction:


Yes as you can see you don't know what to return, because instance is created by class under test and in the test method you don't know which instance is created by createPersonJob method. To solve this problem, you need to use thenAnswer instead of thenReturn method:

Note that Answer interface requires you to implement answer method, which in our case simply returns the first argument (PersonJob instance) of personJobDao.create method.

Now we can write assertions in peace without worrying about returned instance.

Hope you have found this post useful.

We keep learning
Alex.

Download Code
Music: http://www.youtube.com/watch?v=S2a3q0nIsoM

4 comentarios:

Anónimo dijo...

I wonder where is the real issue... Isn't it because createPersonJob method does too much, i.e. it knows about how to create a PersonJob object? If you introduce a factory like this:
PersonJob personJob = personJobFactory.create(person, job);
return this.personJobDao.create(personJob);
then this code is very simple to test.

--
Regards
Tomek Kaczanowski
http://practicalunittesting.com

Alex Soto dijo...

First of all thank you very much for reading my blog, well I agree with you that the solution you provided will make code simple to test, you would only need to mock personJobFactory and personJobDao. You can decide to create a factory for all your classes that requires a M:N relationship, this is good, but you can also follow Persistence Manager pattern which is the responsible (as shown in this post) of managing M:N relationships without a factory.

Regards,
Alex.

Tomasz Nurkiewicz dijo...

If you are forced to use Answers in Mockito, at least wrap them in well named, static methods available somewhere. You must agree this is much more readable:

when(personJobDao.create(any(PersonJob.class))).thenAnswer(withFirstArgument());

Alex Soto dijo...

Hi Tomasz I totally agree with you, in face I usually use this approach or for example when using Converter interface of Lambdaj project I use the same approach you pointed here, but I try to give a very simple example so it is compact, reader will not require to jump over functions to know how they are implemented. But of course in production code I will do what you commented in your comment.

Thank you very much for reading my blog.

Alex.