How NOT to test drive time dependant functionalities

Recommended reading before you read this article: Fest assertions, Testing time dependant functionalities .

Do NOT do this!

I would like to present an example of an attempt to test time dependant functionality in a not very nice in my opinion way. Please see testing time dependant functionalities for the recommended way.

Below I present two very similar ways of trying to test drive time dependant functionalities. Please remember that the recommended way it to introduce a clock class.

Approach by extending Fest (DO NOT DO THIS)

Approach by extending Hamcrest (DO NOT DO THIS)

Why avoid this approach?

Think about it. Is “is within one second” actually what you are looking for? Probably not. You are looking for “is now”.
The other argument is that is reduces readability.

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.

Start from the end

Recommended reading before you read this article: Fest assertions.

Lets assume we want to create a calculator. That calculator will be able to add numbers, so the result of 3+4 should be 7. Please notice that we just expressed an expectation from our calculator.

In most cases I found that starting writing tests from the end is the best way to go. Start from what you expect.

For example:

Stage 1, specify the output, start with the expectation (will not compile)

Stage 2, express what actually has to happen to get to the expectation

Stage 3, make the test pass.

Try to always start with writing one or more assertThat() or verify(). Then proceed to the other parts of the test.This forces you to think about what you actually want to achieve rather then concentrate on implementation and other distractions. I know this example might be too simple to see the benefits clearly unfortunately. It was just to demonstrate the process. Try to implement this process in your projects and you will see the benefits.

JUnit vs Fest by example

I assume you know what a Junit assertion is (assertEquals, assertSame, …). Fest assertions is a mini framework that increases readability of our assertions. Some people still use Hamcrest, but it has many disadvantages when you compare it to fest. (I was using Hamcrest for 6 months, then switched to Fest. Now I use Hamcrest only when I have to. For example when I work on an old codebase, etc.)

Please find a simple and quick comparison of pure Junit asserions and Fest assertions below.

Junit

Fest

The most important things I would say about Fest is:

  1. you don’t have to think about the order of parameters (which one is expected, which one is the actual one)
  2. is has a fluent interface, eg. assertThat(obj).hasSomething(a).hasSomethingElse(b).doesNotContain(b)
  3. when you use it for some time you realize that hamcrest and pure junit offer very poor usability
  4. the assertions are a lot more readable then junit and hamcrest ones

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

Testing logging to log files

Recommended reading before you read this article: Mockito basics

How do we test logging to logs?

We should not do that in general. The solution might be to test if notifications are being sent to support or diagnostic teams though. The implementation of those notifications might go to logs. For example:

A sample implementation of SupportTeam interface might look like this:

The examples above hide logging behind a SupportTeam interface. This seems to be a good modelling example of the real world scenarios. Who looks at the production logs in the real world? Support team in most cases. Then we should notify support team when exception occurs instead of logging to logs. The implementation of SupportTeam interface can log to logs though. Modelling the real world scenarios is in my opinion one of the key OO principles that people often forget about.

Please comment!

[Removing duplication in tests] (Part 1) Move wiring of objects to class attributes

Recommended reading before you read this article: Mockito basics

Hot to get rid of duplicated code in tests

When we have multiple tests and all of them have similar givens we are tempted to extract those common givens to setup method or the field declarations. This might be a good idea when those givens are just wiring of dependencies. In most other cases it might be not a good idea.
Below I include an example for correct removing duplication of “givens” for multiple tests. Moving wiring of objects in field declarations. This way we do not test the wiring in the test, just the business functionality. The wiring should be tested in acceptance or end to end tests, not on unit level.

The example below also replaces string constants with variable names. For example in the tests we don’t care that the username is “john”. We only care that the username passed around is the same object. So we can move the definition of username out of the test to increase readability.

Please note that all fields are marked as final. This ensures that all wiring was done before we start testing the user object.

Before refactor

After refactor

I have not found any other scenarios for removing duplication in tests by moving common code into set up methods or class attributes. All other scenarios where duplication occurs pointed to problems in production code and design issues. Please take a look at all other parts for further details (coming soon).

Please comment! 🙂

Testing time dependant functionalities

Recommended reading before you read this article: Mockito basics, Fest assertions.

How do we test time dependent operations?

Let us assume we have a report and it may me marked as complete. When it is marked as complete the “completed on” date should be set. The easiest approach would be to do a “new Date()” and assign it to “completed on” attribute.

But how do we test it? We have to take an other approach.
The solution is to introduce a Clock object that can be asked for the current time and which we will be able to mock in tests:

Recommended further reading: How NOT to test drive time dependant functionalities

The ultimate test template

Recommended reading before you read this article: Mockito basics, Fest assertions.

When doing OOP we create objects. While doing TDD we should focus on relationships between those objects. That being said, one of the main principles that we should focus on is “Tell Don’t Ask”. We tell object “do this thing” and expect a certain result. This leads us to the “ultimate test template”, a test should have 3 parts: inputs for the tested object, call on the object and then asserting for the expected results, for example:

This is a very basic example just to illustrate the 3 parts of the test. The input is that the User object was supplied with an observer. The output is that if user changed password is that the observer was notified. (This example uses Mockito mocks to create a mock object and then verify if a method was called on it).

You might notice the comments //given //when // then. At the beginning I added them each time I was staring a new test, but after a while I realised that this just adds noise. When you know that each test will have those 3 parts I would skip the comments.

Sometimes the first or third parts may be skipped of course. For example we may skip the first part (the givens are in the same line as the call for readibility):

Or we can skip the first and last part. The third part is moved to the annotation parameters:

InteliJ IDEA users

You might add a live template to your IDE. Go to File->Settings->Live Templates.
Add the listing below to “plain” category. The abbreviation should be “test”.
Do not forget to check “Context -> Java Code”.

Now when you type “test” and pres TAB in a java file the test template will appear.