Convenient mocking in Mockito with JUnit 5 – the official way
Starting with the version 2.17.0 Mockito provides the official (built-in) support for managing a mocking life cycle if JUnit 5 is used.
Getting started
To take advantage of the integration, the Mockito’s mockito-junit-jupiter
dependency is required to be added next to the JUnit 5’s junit-platform-engine
one (see below for details).
After that, the new Mockito extension MockitoException
for JUnit 5 has to be enabled. And that’s enough. All the Mockito annotation should automatically start to work.
import org.junit.jupiter.api.Test; //do not confuse with 'org.junit.Test'! //other imports import org.mockito.junit.jupiter.MockitoExtension; @ExtendWith(MockitoExtension.class) class SpaceShipJUnit5Test { @InjectMocks private SpaceShip spaceShip; @Mock private TacticalStation tacticalStation; @Mock private OperationsStation operationsStation; @Test void shouldInjectMocks() { assertThat(spaceShip).isNotNull(); assertThat(tacticalStation).isNotNull(); assertThat(operationsStation).isNotNull(); assertThat(spaceShip.getTacticalStation()).isSameAs(tacticalStation); assertThat(spaceShip.getOperationsStation()).isSameAs(operationsStation); } }
It’s nice that both a test class and test methods don’t need to be public anymore.
Please note. Having also JUnit 4 on a classpath (e.g. via junit-vintage-engine
) for the “legacy” part of tests it is important to do not confuse org.junit.jupiter.api.Test
with the old one org.junit.Test
. It will not work.
Stubbing and verification
If for some reasons you are not a fan of AssertJ (although, I encourage you to at least give it a try) JUnit 5 provides a native assertion assertThrows
(which is very similar to assertThatThrownBy()
from AssertJ). It provides a meaningful error message in a case of an assertion failure.
@Test void shouldMockSomething() { //given willThrow(SelfCheckException.class).given(tacticalStation).doSelfCheck(); //void method "given..will" not "when..then" cannot be used //when Executable e = () -> spaceShip.doSelfCheck(); //then assertThrows(SelfCheckException.class, e); }
I were not myself if I would not mention here that leveraging support for default methods in interfaces available in AssertJ and mockito-java8 a lot of static imports can be made redundant.
@ExtendWith(MockitoExtension.class) class SpaceShipJUnit5Test implements WithAssertions, WithBDDMockito { ... }
Tweaking default behavior
It also worth to point our that using the JUnit 5 extension Mockito by default works in the “strict mode”. It means that – for example – unneeded stubbing will fail the test. While very often it is a code smell, there are some cases where that test construction is desired. To change the default behavior an @MockitoSettings
annotation can be used.
@ExtendWith(MockitoExtension.class) @MockitoSettings(strictness = Strictness.WARN) class SpaceShipJUnitAdvTest implements WithAssertions, WithBDDMockito { .... }
Dependencies
As I already mentioned, to start using it is required to add a Mockito’s mockito-junit-jupiter
dependency next to a JUnit 5’s junit-platform-engine
one. In a Gradle build it could look like:
dependencies { testCompile 'org.junit.vintage:junit-platform-engine:5.1.0' testCompile 'org.mockito:mockito-junit-jupiter:2.17.2' //mockito-core is implicitly added testCompile 'org.junit.vintage:junit-vintage-engine:5.1.0' //for JUnit 4.12 test execution, if needed testCompile 'org.assertj:assertj-core:3.9.1' //if you like it (you should ;) ) }
Please note. Due to a bug with injecting mocks via constructor into final fields that I have found writing this blog post, it is recommended to use at least version 2.17.2 instead of 2.17.0. That “development” version is not available in the Maven Central and the extra Bintray repository has to be added.
repositories { mavenCentral() maven { url "https://dl.bintray.com/mockito/maven" } //for development versions of Mockito }
In addition, it would be a waste to do not use a brand new native support for JUnit 5 test execution in Gradle 4.6+.
test { useJUnitPlatform() }
IntelliJ IDEA has provided JUnit support since 2016.2 (JUnit 5 Milestone 2 at that time). Eclipse Oxygen also seems to add support for JUnit 5 recently.
Summary
It is really nice to have a native support for JUnit 5 in Mockito. Not getting ahead there is ongoing work to make it even better.
The feature has been implemented by Christian Schwarz and polished by Tim van der Lippe with great assist from a few other people.
The source code is available from GitHub.
Published on Java Code Geeks with permission by Marcin Zajaczkowski, partner at our JCG program. See the original article here: Convenient mocking in Mockito with JUnit 5 – the official way Opinions expressed by Java Code Geeks contributors are their own. |