Talking about design & implementation of solutions using modern OSS frameworks, tools, open standards and cutting-edge technology

Wednesday, December 19, 2012

A TDD approach using Spring Framework + Mockito + Lombok

Intro

This is simple Hello World Java application that successfully combines Spring Framework with Mockito and Lombok. It's just for demonstrative purposes, so the presented example is very simple and used many times before in the literature.

The final goal is to show up how simple is to combine some of the best features of each involved technology with Test-Driven-Development in mind:

Spring Framework: wiring

Mockito: isolation

Lombok: simplicity

Example

A text editor uses and spell checker among other things to make the life of user easier. Depending on the target language, an spell editor may change is behavior and its dependencies as well, for example dictionaries and tokenizers. Simplifying the whole idea you may encounter a contract-driven (interface based) solution like this:

with many possible combinations of spell checkers, dictionaries and tokenizers. For example this one:

where every contract was replaced by a concrete instance. Combinations are multiple, and sometimes you cannot predict all them in a classes/interfaces design.

You want to start engaging TDD for sure, and you want to do it in a top-down fashion. That means, start testing the text editor first, then the spell checker, then the remaining pieces. You also want to do it in isolation, so spell checker and the remaining implementations aren't involved in editor tests, and it's your desire to obtain zero infrastructure code (no constructor calls). As a plus no getter nor setter nor trivial constructor implementations.

What to test?

Our test will be very simple as well, here is the top-down ordered list (remember it's a simplification of the reality):

1- Given an Editor, when a new text is pasted it should be added.
2- Given an Editor, when a new text is pasted the spell should be checked against the appended text.
3- Given an English spell checker, when a word is not found in a dictionary during the spell check then it must be signaled as misspelled and returned back.

You may be wondering, why should I test these obvious use cases? Trust
me, it's very important to cover all possible scenarios if you really
want to delivery software with built-in quality. This is the hidden synergy behind TDD.

NOTE: Lombok must be attached to Spring Tool Suite (or Eclipse) for completion at development time. Copy your lombok.jar to STS installation folder and append the following settings to your STS.ini (eclipse.ini):

Right click on test case and Run As JUnit test. The test will fail but corner stones are ready to support more agile tests. Make the test pass by implementing the paste() method. Oops! remember to remove the fail() from the test.

Re-run the test, this time also using a Maven run configuration like this:

mvn test

The spring default behavior is to cache the application context between different tests in the same test case. They also introduced the annotations @TestExecutionListeners and @DirtiesContext to mark the application context as dirty after each test:

The next step is to provide an spell checker mock to the application context:

Remove the fail() from the test and run all tests and you will get a test failure saying: 'Wanted but no invoked: spellChecker.check("Hello everybody!")'. That makes sense since we are not invoking the SpellChecker.check() from Editor.paste(). In fact haven't create any kind of dependency Editor -> SpellChecker. Let's do it at class level and force its injection at construction time using Lombok's @RequiredArgsConstructor: