Pages

Spring and Mockito

A modern web application written using Spring would use Dependency Injection to loose coupling among the components in the project. This is good, and help us to write more flexible code, as we have seen in a previous post. However this also mean that we need a way to test code that uses a component that is not actually there. Mock testing its here to help us. We'll see here how to use Mockito to achieve this result.

Say that my Spring Boot Application has a RestController named KnightController. It maps a request for the /quest resource to a call to the method doQuest() on the Knight resource owned by the controller.
@RestController
public class KnightController {
    @Resource
    private Knight knight;

    @RequestMapping("/quest")
    public String quest() {
        return knight.doQuest();
    }
}
Knight is just an interface that declares a single method, doQuest(). The beauty of this approach is that we can send any kind of knight in a quest, the only requirement being he implements this interface. For instance, here is a BraveKnight:
public class BraveKnight implements Knight {
    private Quest quest;

    public BraveKnight(Quest quest) {
        this.quest = quest;
    }

    @Override
    public String doQuest() {
        return quest.embark();
    }
}
This Knight owns a Quest, that is defined at runtime, by Constructor Injection, i.e., the actual quest this knight is going to embark is injected in the knight by use of the ctor. As for the Knight, also Quest is an interface with a single method, embark(). Again, in this way a knight is very flexible, having a way to change by injection which is the quest he would embark.

Even if there is more to say on this architecture, here we are interested in see how we can test if what we have now works as expected. Meaning, I would like to write a test case where I create a Quest, I inject it in a BraveKnight, and when I call his doQuest() method I see if the quest embark() method is called. We can't do that in the real world, since Quest is just an interface. But we can mock it, for instance using Mockito.

I need to add the mokito-core dependency in my pom file for the test scope
And then I can create a JUnit-Mockito test case in the test folder. I named it BraveKnightTest.
Its structure is straighforward, let's spend in any case a few words on the first and last line:
Quest quest = Mockito.mock(Quest.class); // 1
// ...
Mockito.verify(quest, Mockito.times(1)).embark(); // 2
1. Create an instance from a mock class that implements the Quest interface.
2. Verify that the method embark() defined on our mock Quest object has actually been called once, as expected.

I have written this post while reading the first chapter of Spring in Action, Fourth Edition by Craig Walls. While doing it, I have ported the original code to a Maven Spring Boot Web project on the STS IDE, using AspectJ annotations instead of the classic xml configuration.

Full source code is on github in the springInAction folder.

No comments:

Post a Comment