Mock test on a Spring resource

Following the first chapter of Spring in Action, Fourth Edition by Craig Walls, I'm about to use the constructor injection (a Dependency Injection technique) to implement a IoC (Inversion of Control) relation between a Knight and its own Quest. No disrespect is meant, however I slightly change the original code to adapt it to a standard Boot Maven STS Spring Starter Project with Web dependency.

I put my SpringBootApplication in the dd.sia.knights package, and I created a couple of sub-packages, controller and logic. In the first one I have put a RestController, named KnightController, that owns a Resource Knight and performs a RequestMapping between the URI /quest and the method quest():
@RestController
public class KnightController {
    @Resource
    private Knight knight;

    @RequestMapping("/quest")
    public String quest() {
        return knight.doQuest();
    }
}
I put all the classes rooted in the Knight and Quest interfaces in the logic sub-package. They both have a single method, doQuest() and embark(), returning a String.

Constructor Injection

I created a concrete BraveKnight that implements Knight and has as private field a Quest. Which Quest a particular BraveKnight has is decided at runtime, injecting the actual Quest through the constructor:
public class BraveKnight implements Knight {
  private Quest quest;

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

  public String doQuest() {
    return quest.embark();
  }
}

Mock Test with Mockito

Now we'd like to check if the class structure we designed works as expected. We can't perform normal unit test with JUnit for the reason that we don't currently have any concrete Quest to inject in our Knight. However we can mock-test it.

To do that we have to add a mokito dependency in our project POM, pom.xml, adding mokito-core from org.mockito for test scope. Then I added a JUnit-Mockito test case for BraveKnight with a single test function:
@Test
public void testDoQuest() {
    Quest quest = Mockito.mock(Quest.class); // 1
    BraveKnight knight = new BraveKnight(quest); // 2
    knight.doQuest(); // 3
    Mockito.verify(quest, Mockito.times(1)).embark(); // 4
}
1. A mock Quest is created.
2. Injecting the mock quest in a BraveKnight.
3. Call the knight method.
4. Ensure that the embark() method of my mock quest has been called once in this context.

Full source code is on github in the springInAction folder.

No comments:

Post a Comment