Reputation: 143
I am trying to create unit test for my interceptor class ApiMetrics
@Provider
public class ApiMetrics implements ContainerRequestFilter, ContainerResponseFilter {
@Context
ResourceInfo resourceInfo;
@Context
HttpServerRequest httpServerRequest;
....
}
My Test Class is as follows, but on using @Mock annotation i'm getting NPE on resourceInfo and httpServerRequest when trying to mock any of their methods (getResourceMethod). Also, I tried @Inject, @InjectMock as I'm not sure how to mock a @context field but got dependency error.
@QuarkusTest
class CLASS_ApiMetrics_UT_Test {
@Inject
ApiMetrics apiMetrics;
@Mock
ResourceInfo resourceInfo;
@Mock
HttpServerRequest httpServerRequest;
....
}
Also if I use the following for mocking,
ResourceInfo resourceInfo = Mockito.mock(ResourceInfo.class);
HttpServerRequest httpServerRequest = Mockito.mock(HttpServerRequest.class);
when(resourceInfo.getResourceMethod()).thenReturn(method);
when(httpServerRequest.getFormAttribute(BODY_REQUESTER_ID)).thenReturn(expectedRequesterId);
I get this error for the mocked Classes Method threw 'org.jboss.resteasy.spi.LoggableFailure' exception. Cannot evaluate com.sun.proxy.$Proxy141.toString()
Upvotes: 1
Views: 426
Reputation: 11502
The resourceInfo
and httpServerRequest
fields should be annotated with @InjectMock
, not @Mock
.
The @Mock
annotation doesn't actually mark an injection point, which is why nothing is getting injected and you're seeing the NPE. io.quarkus.test.Mock
is intended to be applied to an actual mock implementation, not the injection point. It defines a global mock which would be used everywhere something used @Inject
, in test mode.
@InjectMock
Here's what your test should look like
@QuarkusTest
class CLASS_ApiMetrics_UT_Test {
@Inject
ApiMetrics apiMetrics;
@InjectMock
ResourceInfo resourceInfo;
@InjectMock
HttpServerRequest httpServerRequest;
@BeforeEach
public void setup() {
when(resourceInfo.getResourceMethod()).thenReturn(method);
when(httpServerRequest.getFormAttribute(BODY_REQUESTER_ID)).thenReturn(expectedRequesterId);
}
@Mock
If you wanted to use the global @Mock
approach instead, you would do something like
@Inject
ResourceInfo resourceInfo;
in the test class (note that it's just a normal @Inject
). Then you'd manually define a mock implementation class:
@Mock
public class MockResourceInfo implements ResourceInfo {
public void doAThing() {
// mock implementation goes here
}
public void notifyInvoiceAlreadySent(Invoice invoice) {
}
}
That way of doing it is sometimes handy, but it has the disadvantage that Mockito can't help you define the mock, and the same mock implementations is used in all test classes. So generally @InjectMock
is better.
The Quarkus docs have more explanation of the different mock annotations.
Upvotes: 0
Reputation: 18413
You can write a resource visible only for your test(s); no need to mock @Context
objects because during test all is working as in a real http call
PS: I suspect this type of objects can't be mocked,but someone from Quarkus team can give you a precise answer about that.
@QuarkusTest
@TestHttpEndpoint(TestResource.class)
class CLASS_ApiMetrics_UT_Test {
@Inject
ApiMetrics apiMetrics;
@Test
void test() {
RestAssured.given().get().then().statusCode(200);
assertCondition(expected, apiMetrics.propertyToTest);
}
@Path("api-metrics-test")
public static class TestResource {
@Path("")
@GET
public void doSomething() {...}
}
}
Upvotes: 0