Reputation: 7694
I am trying to write unit tests for Quarkus using Mockito, but I fail mocking things.
Here is a minimal (not) working example :
package com.my.package;
import io.quarkus.test.junit.QuarkusTest;
import org.mockito.Mockito;
import org.mockito.Mock;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
@QuarkusTest
public class LoadCalculatorServiceTest {
public class Foobar {
public int baz;
public void setBaz(int baz) {
this.baz = baz;
}
public int getBaz() {
return this.baz;
}
}
@Mock
Foobar foobar;
// Foobar foobar = new Foobar(); // doesn’t work either
@Test
public void myTest() {
Mockito.when(foobar.getBaz()).thenReturn(4); // NullPointer
Assertions.assertEquals(4,foobar.getBaz());
}
}
The test crashes on a NullPointer.
I read such issues may be fixed by annotating the test with @RunWith(MockitoJUnitRunner.class)
, @ExtendWith(MockitoExtension.class)
(which for some reason I expected @QuarkusTest
to do anyway ?), however I fail to find the correct imports to load them.
I tried org.junit.jupiter.api.MockitoExtension
, org.junit.runner.RunWith
and variations, without success.
Here is the relevant part of my pom.xml
:
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.quarkus</groupId>
<artifactId>quarkus-junit5-mockito</artifactId>
<scope>test</scope>
</dependency>
What am I missing ?
Upvotes: 6
Views: 6859
Reputation: 1756
When you are extending it with MockitoExtension
, there's no necessity for the presence of @QuarkusTest
. Simply include @ExtendWith(MockitoExtension.class)
and exclude @QuarkusTest
from your code and it should be goood.
However, if you intend to retain @QuarkusTest
, you must utilize @InjectMock from Quarkus for this purpose. @InjectMock
facilitates the creation of a Mockito mock. Thus, the revised code would look like below:
@QuarkusTest
public class LoadCalculatorServiceTest {
@ApplicationScoped
static class Foobar {
public int baz;
public void setBaz(int baz) {
this.baz = baz;
}
public int getBaz() {
return this.baz;
}
}
@InjectMock
Foobar foobar;
@Test
public void myTest() {
when(foobar.getBaz()).thenReturn(4);
Assertions.assertEquals(4,foobar.getBaz());
}
}
Upvotes: 1
Reputation: 33
I'm using quarkus 1.8.1.Final, with mockito 3.6.0, I had the same issue with @Mock annotation and I followed the answer from Skippy le Grand Gourou and it didn't work, so I deleted the @QuarkusTest annotation, and delete de MockitoAnnotations.initMocks(this) method, my mockito version has deprecated this, then the test run with the @Mock annotation. I'm new doing Quarkus so I don't know very well the side effects of removing @QuarkusTest
Upvotes: 0
Reputation: 7694
I figured the original code works with plain-style mocks :
Foobar foobar = Mockito.mock(Foobar.class);
So the question is actually how to make the @Mock
annotation work ? There are several things needed for that :
The @RunWith
annotation has been replaced (or should we say upgraded) by @ExtendWith
in JUnit5. It can be imported in Quarkus using import org.junit.jupiter.api.extension.ExtendWith;
.
@RunWith
is usually used as @ExtendWith(MockitoExtension.class)
. MockitoExtension can be imported in Quarkus using import org.mockito.junit.jupiter.MockitoExtension;
. Beware that the mockito-junit-jupiter
dependency (from the org.mockito
group) must be added to the pom.xml
, since the quarkus-junit5-mockito
packages do not depend on it.
Mocks have to be initialized by MockitoAnnotations.initMocks()
before the tests. Note that although it may seem to make more sense to use @BeforeAll
for the setup function, apparently it is not the point of this annotation and one should use @BeforeEach
(the former needs the setup to be static, and IIUC the setup function will be called before each test anyway).
Then finally the @Mock
annotation should work.
To summarize, the original code would become :
package com.my.package;
import io.quarkus.test.junit.QuarkusTest;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.MockitoAnnotations;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Assertions;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.mockito.junit.jupiter.MockitoExtension;
@QuarkusTest
@ExtendWith(MockitoExtension.class)
public class LoadCalculatorServiceTest {
public class Foobar {
public int baz;
public void setBaz(int baz) {
this.baz = baz;
}
public int getBaz() {
return this.baz;
}
}
@BeforeEach
public void setup() {
MockitoAnnotations.initMocks(this);
}
@Mock
Foobar foobar;
@Test
public void myTest() {
Mockito.when(foobar.getBaz()).thenReturn(4);
Assertions.assertEquals(4,foobar.getBaz());
}
}
with the following addition to the pom.xml
:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-junit-jupiter</artifactId>
<scope>test</scope>
</dependency>
Upvotes: 7