Avoid argument captors

Why avoid argument captors?

They decrease readability of the tests. It is a code smell. It is very probable that if you use argument captor your class violates one of the SOLID rules. The most common violation in my experience is not sticking to SRP.

Example 1

I have found on the web an example of how to use argument captors. This is the test I found:

The author had probably in mind showing how argument captors work. I agree that it is a good thing to show stuff on the web. On the other hand if I was test driving implementation of inviteToParty method I would go for just a simple verify:

In my opinion it is far more readable. I don’t see the point in using argument captor in this case.

Example 2

I found another example usage of argument captor on the web.
The solution presented there looks like this:

This is a clean test. I like it. But If I was to write that test I would probably split that MailDeliverer. I would split the the creation of Email object and invoking external system. When you order a laptop you don’t have to assemble it yourself, it is assembled for you in a factory. Some may say that this is a bit over the top in this case, but this is just to stress the principle I have in mind. This is what I came up with:

And:

What do YOU think? 🙂 Please comment and subscribe to RSS! 🙂

[Example] Top-down ATDD/TDD with acceptance tests covering third party API

What is ATDD?

ATDD is Acceptance Test Driven Development. In one short sentence: we start with an acceptance test that describes the functionality we want to implement from users point of view. Acceptance tests ideally should be “black box” tests. They should talk to the application only through the interfaces it exposes.

The story

We will implement a webservice that adds numbers and returns the result. Since we want to do the simplest thing possible we will use the Servlet API.

The acceptance test

We start with an acceptance test. It is an example expected behaviour of the system from users point of view. So in this case the user sends a request to our webservice to add two numbers and expects a result in return. Please notice we use Jetty embeded server to startup the application (the Application class and its start and stop methods):

We run the test. Since we don’t have any web app under that url we will get 404 NotFound response instead of 200 OK.
So we add a src/main/webapp directory with a web.xml file. That web.xml file should define a servlet so that we get a 200 response.

We create the servlet class as well:

We run the test. Now we get assertion error “Expected: ‘7’ Actual: ” “. So finally we can proceed to a unit test for our CalculatorServlet!

Start with a test:

Notice that we specyfy that the servlet class will be just an adapter. It extracts data from request, sends message to calculator and then stores the result in response. It does not do any calculations.
In this adapter we mock third party interfaces. The assumptions we made while mocking the method calls are verified in the end-to-end/acceptance test.

Notice that the tests uses “OPERANDS” constant that is defined in the production code. This is because the acceptance tests already test the paramater name. We do not want to have many test failed with the same reason. So we reduce the duplication in this case. Now the “operands” keyword is in the production class and in the acceptance test only.

No we can write the production code:

We run the unit test and it passes. But when we run the acceptance test it fails with RuntimeException on Calculator.add(). So we start with a test for it:

The test fails, so we implement the production code:

Now if we run the unit and acceptace test, ALL PASS!

Conclusions

We started with a black box acceptance test. We continued implementing the application parts only when we had a failing test with a clear error/assertion message. The third party API calls we mock in unit tests are testes also on acceptance level.

If you wish to get more from ATDD please take a look at acceptance test frameworks. There are many of them on the web. Recently I described one of them. Using those frameworks can save a lot of your time.

Please notice I was using totallylazy while implementing list operations. It is a functional library with lazy loading (cool math stuff, infinite sequences, fluent interface, …). For further information please look at totallylazy home page.

Please comment and subscribe to RSS! 🙂

Do not mock Value and Data Transfer Objects

Recommended reading before you read this article: Mockito basics

Mocking VOs and DTOs is harmful

When you write a test and need an instance of a Value Object or a Data Trasfer Object it is best to create a new instance of it instead of mocking it.

Mocking decreases readability and might cause more maintenance issues while refactoring. Mocking should be a way of learning about messages sent between objects. For further details please read Mocks Aren’t Stubs.

Please find an example below. Notice the huge difference in readability:

Your VOs and DTOs are probably immutable and some of them might even have no behaviour at all. There is no point in mocking them.

Do not mock third party classes

Recommended reading before you read this article: Mockito basics

Mock only your classes. Do not ever mock external third party classes.

When you create a mock object and tell it to behave in a certain way you make assumptions about the class you are mocking. If you are going to implement the class that you just mocked, that is perfect, it is what you need. You have a set of requirements for the new class.

If you mock a third party class you make those assumptions about an already existing class that is not yours. Your assumptions may be wrong. Yours assumptions can be right but the class might change and your assumptions can get out of date. These are the main reasons you should never mock an external class.

The right way to solve this issue is to have end-to-end and/or acceptance tests that cover critical paths through the system. Those tests should use those third party classes/jars/… In that case you can get fair coverage and tell if the third party software behaves in the way you expect it to.

EDIT 3 Sep 2011:
Please take a look at my example of how to do end to end testing on unit-mocked third party APIs.

Mockito basics by example

What is a mock object?

Mock is an object that simulates the behavior of a real object. We very often use those objects in tests.

When doing TDD we try to find the messages that are being send between objects that we create. Mocks are an easy way to simulate sending a message or checking if a message was received.

How does Mockito help do that?

Mockito helps us. We don’t have to write mock objects on our own. We can ask Mockito to create a mock object for us. Then we can program the mock object to behave in certain ways using Mockito helper methods. Please find a basic mockito instruction set demonstration below:

Recommended further reading: Mocks Aren’t Stubs