Reputation: 9393
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.
Upvotes: 8
Views: 13488
Reputation: 131466
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.
Upvotes: 6