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:


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

Commit to SCM frequently

I try to commit and update as frequent as possible. The ideal scenario is to commit and update after we have finished a small chunk of work. That might be even each 10 minutes! This approach encourages thinking in small steps. If an unexpected test fails we can revert without much cost. If the refactor we are doing goes not as we expected we can revert and try once again. It some cases it will be cheaper to revert than keep doing something that looks not pleasent form the beginning. It worked for me many times.

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!


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! 🙂