Consider the following class under test:
public class SomeClass {
@Autowired
private SomeDependency someDependency;
public int inc(int i) {
someDependency.doSomething();
return i + 1;
}
}
How can I mock (preferably with Mockito) someDependency
in a JUnit 5 (5.0.1
) test for a Spring Boot 2 (2.0.0.M2
) application? When I try to invoke SomeClass#inc(int)
it yields a NullPointerException
because the autowired dependency isn't injected.
To achieve this, we can use the mocking support provided by Spring Boot Test. To check the Service class, we need to have an instance of the Service class created and available as a @Bean so that we can @Autowire it in our test class. We can achieve this configuration using the @TestConfiguration annotation.
Mockito 1 runner (MockitoJUnitRunner
class) is not designed to run JUnit 5 tests.
So annotating your class with :
import org.mockito.junit.MockitoJUnitRunner;
@RunWith(MockitoJUnitRunner.class)
public class MyJUnit5Test {
will have no effect.
To be able to use the @Mock
annotation, you could invoke before each test :
MockitoAnnotations.initMocks(this);
in a method annotated with JUnit 5 @BeforeEach
.
But from now a better alternative to not repeat this pre-processing in each JUnit test class is using the MockitoExtension
class provided by the mockito-junit-jupiter
dependency.
Code example
Supposing the SomeDependency
class declared as :
@Component
public class SomeDependency {
public String returnThat() {
return "that";
}
}
You could so mock the dependency in this way in your unit test :
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
import davidhxxx.example.angularsboot.SomeDependency;
@ExtendWith(MockitoExtension.class)
public class SomeClassTest {
@Mock
SomeDependency someDependencyMock;
private SomeClass someClass;
@BeforeEach
public void setup(){
someClass = new SomeClass(someDependencyMock);
}
@Test
void myFirstTest() {
Mockito.when(someDependencyMock.returnThat()).thenReturn("mock result");
Assertions.assertEquals("mock result", someClass.inc());
}
}
Note that SomeClass
has to provide a way to set its SomeDependency
dependency.
You should add a constructor that accepts an instance of.
Using setter
is also a way while it provides mutability.
pom.xml requirements
1) You can add the spring-boot-starter-test
dependency that includes Mockito and other useful things in inherited dependencies :
<dependencies>
...
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
...
</dependencies>
Add also the junit-jupiter-engine
dependency and all other optional JUnit 5 dependencies that you require :
<dependencies>
...
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-engine</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<version>2.18.0</version> <!-- version to specify as not provided by Spring Boot dependencies -->
<scope>test</scope>
</dependency>
</dependencies>
You don't need to specify version for the junit-jupiter-engine
artifact but you may need for other JUnit 5 dependencies such as junit-jupiter-params
.
Hoping that this would be not required any longer in next versions of Spring Boot.
2) Beware : if you use a Spring Boot version that pulls the
2.20 version of the maven-surefire-plugin
it will not work. So you will have to override the maven-surefire-plugin
plugin configuration to specify a version compatible with JUnit 5 (that is 2.19 or 2.21 and later).
For example the 2.0.0.M5 version of Spring Boot pulls maven-surefire-plugin:2.20 and so reconfiguring the plugin such as the following is required :
<plugins>
...
<plugin>
<artifactId>maven-surefire-plugin</artifactId>
<version>2.19</version>
<dependencies>
<dependency>
<groupId>org.junit.platform</groupId>
<artifactId>junit-platform-surefire-provider</artifactId>
<version>1.0.0</version>
</dependency>
</dependencies>
</plugin>
...
<plugins>
It will generate a Maven warning :
Overriding managed version 2.20.1 for maven-surefire-plugin
Good news : from the 2.0.1.RELEASE version of Spring Boot this issue is solved as the maven-surefire-plugin version was updated to use 2.21.0
and later version that solves the issue.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With