Exercise 0: Target
The target of this exercise is to learn working with Mockito
-
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
Add interface and controller
-
Start with a clean project or an empty package
-
Add an interface Calculator
-
Add interface Calculator with methods
int add(int a, int b);
Exercise 2: Add Mockito
Step 0: Prerequisites
-
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
-
-
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
Step 1: Validate interface and add controller
Learn to work with Mockito
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
-
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
package nl.ing.testing.utils;
public interface Calculator {
int add(int a, int b);
int pow(int a, int b);
}
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
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:
-
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
-
10 minutes
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);
}
}
// 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;
}
}
// 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
-
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
-
You have to tell Mockito what is a positive result using Mockito.when