Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to mock rest clients when unittesting a Quarkus application?

Tags:

quarkus

Quarkus getting started unittest describes how to mock injected services. However when trying to apply this to an injected rest client this does not seem to work.

In my application the class attribute to be injected is defined like this

  @Inject
  @RestClient
  MyService myService;

In my test code I created a mock service like this:

@Alternative()
@Priority(1)
@ApplicationScoped
public class MockMyService extends MyService {

    @Override
    public MyObject myServicemethos() {
        return new MyObject();
    }
}

Please note that this service is not registered or annotated as a RestClient. Running my unittests like this gives the following error:

org.junit.jupiter.api.extension.TestInstantiationException: TestInstanceFactory [io.quarkus.test.junit.QuarkusTestExtension] failed to instantiate test class [...MyMediatorTest]: io.quarkus.builder.BuildException: Build failure: Build failed due to errors
    [error]: Build step io.quarkus.arc.deployment.ArcAnnotationProcessor#build threw an exception: javax.enterprise.inject.spi.DeploymentException: javax.enterprise.inject.UnsatisfiedResolutionException: Unsatisfied dependency for type ...MyService and qualifiers [@RestClient]
    - java member: ...MyMediator#myService
    - declared on CLASS bean [types=[java.lang.Object, ...MyMediator], qualifiers=[@Default, @Any], target=...MyMediator]

    at org.junit.jupiter.engine.descriptor.ClassTestDescriptor.invokeTestInstanceFactory(ClassTestDescriptor.java:314)
  ...

I can probably overcome this by adding an additional service layer. But that feels like heading in the wrong direction.

How can I solve this.

Kind regards,

misl

like image 678
misl Avatar asked Dec 14 '22 11:12

misl


1 Answers

I just hit the same problem. There seems to have updates in the documentation and some corner cases that I faced, but google search sent me here first so I'll add my investigation results for future readers.

According to the documentation you already do not need creating mock class https://quarkus.io/guides/getting-started-testing#using-injectmock-with-restclient

but can use it like

Service class

@RegisterRestClient(configKey = "country-api")
@ApplicationScoped
public interface MyService

Service Usage

@Inject
@RestClient
MyService myService;

Mock it in the test like

@InjectMock
@RestClient 
MyService myService;

So far so good but following the documentation https://quarkus.io/guides/rest-client if you need configKey you will probably finish with

# Your configuration properties
country-api/mp-rest/url=https://restcountries.eu/rest #
!!country-api/mp-rest/scope=javax.inject.Singleton # /

in your config file. And then will hit these issues

Ability to use InjectMock on MicroProfile RestClient # 8622

Usage of InjectMock on MicroProfile RestClient # 9630

Error when trying to Test RestClient # 12585

that say: if you are using configKey with RegisterRestClient have to care TO NOT HAVE

country-api/mp-rest/scope=javax.inject.Singleton # 

in the config file which takes precedence before the @ApplicationScoped on the MyService interface

like image 167
isilona Avatar answered May 16 '23 07:05

isilona