Exercise 0: Target

The target of this exercise is to learn working with Mockito

What does Mockito bring to us
  • It helps you to unittest a class which has an interface as a field an there is not a concrete class (yet)

  • So you want to unittest a class but that class has an interface type as field

Exercise 1: Setting up

Target

Add interface and controller

Roadmap
  • Start with a clean project or an empty package

  • Add an interface Calculator

Steps
  • Add interface Calculator with methods

int add(int a, int b);

Exercise 2: Add Mockito

Step 0: Prerequisites

Things we have done before starting this
  • We have created a pom.xml using start.spring.io

    • In this pom.xml there are dependencies to spring-boot-starter-test

      • In this dependencies somewhere there the framework Mockito is included

Part of pom which includes testing
<dependency>
                        <groupId>org.springframework.boot</groupId>
                        <artifactId>spring-boot-starter-test</artifactId>
                        <scope>test</scope>
</dependency>

Step 1: Validate interface and add controller

Target

Learn to work with Mockito

Roadmap

During this assignment you will create a test for the CalculatorController which contains an interface Calculator which is off course not instantiatable!!! and you still have and want to test the functionality of the CalculatorController his GET method

Steps
  • Validate that you have an interface Calculator as mentioned above

  • Create a class CalculatorController

  • Add the private field calculator of type Calculator to the CalculatorController;

    • private Calculator calculator;

  • Add a GET method which returns the value of the result of a+b using the Calculator interface

  • The GET method of the Controller should invoke the add method of the Calculator interface

Something like this (the calculator interface)
package nl.ing.testing.utils;

public interface Calculator {

    int add(int a, int b);
    int pow(int a, int b);

}
Somethink like this (the CalculatorController)
package nl.ing.testing.controller;


import nl.ing.testing.utils.Calculator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequestMapping("/api/calculator")
public class CalculatorController {

    @Autowired
    private Calculator calculator;


    @GetMapping
    public int add(int a, int b) {
        return this.calculator.add(a,b);
    }

    public String powerResult(int a, int b) {

        String result = String.format("%d to the power of %d results to %d", a, b, this.calculator.pow(a,b));

        return result;

    }
}

(remind yourself that the private field calculator in Controller is an interface)

Step 2: Add Mockito to test the add method of the Controller with a Unittest

Add a Unittest with Mockito to test the add method of the controller (like this)
package nl.ing.testing.controller;

import nl.ing.testing.utils.Calculator;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;

public class CalculatorControllerTest {


    @InjectMocks
    private CalculatorController calculatorController;

    @Mock
    private Calculator calculator;

    @BeforeEach
    public void init() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    public void testAdd() {
        Mockito.when(this.calculator.add(3,4)).thenReturn(7);
        Assertions.assertEquals(7, this.calculatorController.add(3, 4));
    }

    @Test
    public void testAdd2() {
        Mockito.when(this.calculator.add(3,3)).thenReturn(10);
        Assertions.assertEquals(10, this.calculatorController.add(3, 3));
    }

    @Test
    public void testAdd3() {
        Mockito.when(this.calculator.add(3,3)).thenReturn(6);
        Assertions.assertEquals(6, this.calculatorController.add(3, 3));
    }

    @Test
    public void testPower() {

        Mockito.when(this.calculator.pow(2,3)).thenReturn(8);
        String result = this.calculatorController.powerResult(2,3);

        Assertions.assertEquals("2 to the power of 3 results to 8", result);
    }
}

And again …​ you should be surprised that it even works since Calculator is an interface

Assignment: Add String getResultOfPower(int a, int b); to the Controller

After having a running version of the above code, please do the following:

Steps
  • Add the method signature int pow(int a, int b); to the Calculator interface

  • create a method in CalculatorController method which returns the following String

    • "2 to the power of 3 results to 8"

  • The Calculator’s mock his pow method returns the Math.pow(a,b) result, hence Math.pow(2,3) is 8 since 2 to the power of 3 is 8

  • Test the method using a Unittest, mocking out the Calculator his pow method

Time available:
  • 10 minutes

Solution CalculatorControllerTest
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
// Test
package nl.example.volleybal.controller;

import nl.example.volleybal.utils.Calculator;

public class CalculatorControllerTest {


    @InjectMocks
    private CalculatorController calculatorController;

    @Mock
    private Calculator calculator;

    @Test
    public void testAdd() {
        Mockito.when(this.calculator.add(3,4)).thenReturn(7);
        Assertions.assertEquals(7, this.calculatorController.add(3, 4));
    }

    @Test
    public void testAdd2() {
        Mockito.when(this.calculator.add(3,3)).thenReturn(10);
        Assertions.assertEquals(10, this.calculatorController.add(3, 3));
    }

    @Test
    public void testAdd3() {
        Mockito.when(this.calculator.add(3,3)).thenReturn(6);
        Assertions.assertEquals(6, this.calculatorController.add(3, 3));
    }

    @Test
    public void testPower() {

        Mockito.when(this.calculator.pow(2,3)).thenReturn(8);
        String result = this.calculatorController.powerResult(2,3);

        Assertions.assertEquals("2 to the power of 3 results to 8", result);
    }
}
Solution CalculatorController
// Controller
package nl.example.volleybal.controller;


import nl.example.volleybal.utils.Calculator;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class CalculatorController {

    private Calculator calculator;


    public int add(int a, int b) {
        return this.calculator.add(a,b);
    }

    public String powerResult(int a, int b) {

        String result = String.format("%d to the power of %d results to %d", a, b, this.calculator.pow(a,b));

        return result;
    }
}
Solution Calculator
// Calculator
package nl.example.volleybal.utils;

public interface Calculator {

    int add(int a, int b);

    int pow(int a, int b);

}

Summary

During this exercise we learned to work with Mockito

What does Mockito bring to us
  • It helps you to unittest a class which has an interface as a field an there is not a concrete class (yet)

  • It separates the testing of the interface type (Calculator) and the Controller

What to do to get Mockito running
  • You have to tell Mockito what is a positive result using Mockito.when