A little bit late, but I try to answer the question for future reference.
Although I agree with the @Héctor's comment, it could be useful to test the MicroProfile rest client itself (e.g. to actually test an error handler) or in the bean which the rest client is injected in.
Anyway, you need a mock server such as WireMock. The official guide for Quarkus actually covers this topic.
I can report here an example for it (which I took from here).
Add this dependency to your pom.xml (if you are using Maven):
<dependency>
<groupId>com.github.tomakehurst</groupId>
<artifactId>wiremock-jre8</artifactId>
<scope>test</scope>
<version>${wiremock.version}</version>
</dependency>
Create a class which will start the mock server befor the tests are executed (and which will shutdown it once they are all executed):
package org.acme.getting.started.country;
import java.util.Collections;
import java.util.Map;
import com.github.tomakehurst.wiremock.WireMockServer;
import io.quarkus.test.common.QuarkusTestResourceLifecycleManager;
import static com.github.tomakehurst.wiremock.client.WireMock.*;
public class WiremockCountries implements QuarkusTestResourceLifecycleManager {
private WireMockServer wireMockServer;
@Override
public Map<String, String> start() {
wireMockServer = new WireMockServer();
wireMockServer.start();
//define a static response when the request matches a url declared as a regex
stubFor(get(urlEqualTo("/v2/name/GR"))
.willReturn(aResponse()
.withHeader("Content-Type", "application/json")
//read the WireMock docs: you can even use a json file in /resources/__files/ (default expected location) in place of a string
.withBody(
"""
[
{
"name": "Ελλάδα",
"capital": "Αθήνα"
}
]
"""
)));
//remap the base url of the external service to the base url of the mock server
return Collections.singletonMap("org.acme.getting.started.country.CountriesService/mp-rest/url", wireMockServer.baseUrl());
}
@Override
public void stop() {
if (null != wireMockServer) {
wireMockServer.stop();
}
}
}
Memento: at the moment, you cannot test a @Singleton bean, so put on the rest client interface the annotation @ApplicationScoped.
Finally, use this class in the actual test class:
package org.acme.getting.started.country;
import javax.inject.Inject;
import io.quarkus.test.common.QuarkusTestResource;
import io.quarkus.test.junit.QuarkusTest;
import org.eclipse.microprofile.rest.client.inject.RestClient;
import org.junit.jupiter.api.Test;
import static org.assertj.core.api.Assertions.assertThat;
@QuarkusTest
@QuarkusTestResource(WiremockCountries.class)
class RegularCountriesServiceTest {
@Inject
@RestClient
CountriesService countriesService;
@Test
void testGR() {
// assertThat(countriesService.getByName("GR")).hasSize(10).extracting("name").contains("Greece");
assertThat(countriesService.getByName("GR")).hasSize(1).extracting("name").contains("Ελλάδα");
}
}
If you want to test the rest client one level above, all you need to do is reusing the wrapper class for the mock server and inject with @Inject the bean which declares the rest client as its dependency. Do something like this:
@QuarkusTest
@QuarkusTestResource(WiremockWrapperAsBefore.class)
class MyBusinessClassTest {
@Inject
MyBusinessClass myBusinessClass;
@Test
void testMyRestCleintInjectedIntoMyBusinessClass() {
ResponseDTO dto = myBusinessClass.methodWhichCallsMyMicroProfileRestClient(String someParam);
assertNotNull(dto);
}
}
Otherwise, it could be useful in another scenarios to create a proxy implementation with RestClientBuilder for the MicroProfile rest client interface, as shown here:
import java.net.MalformedURLException;
import java.net.URI;
import org.eclipse.microprofile.rest.client.RestClientBuilder;
import static org.junit.Assert.assertNotNull;
import org.junit.Test;
public class RestClientTest {
@Test
public void init() throws MalformedURLException {
URI baseURI = URI.create("http://localhost:8080");
PingClient client = RestClientBuilder.newBuilder().
baseUri(baseURI).
build(PingClient.class);
assertNotNull(client);
String result = client.ping();
assertNotNull(result);
}
}
The corresponding interface is easy to guess, but it is like follows:
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.eclipse.microprofile.rest.client.inject.RegisterRestClient;
@Path("/restclient/resources/ping")
@RegisterRestClient
public interface PingClient {
@GET
String ping();
}
You won't need the following dependencies in that case if you are using Quarkus, but I will report the anyway from the link above in case someone is using MicroProfile but not Quarkus:
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>javax</groupId>
<artifactId>javaee-api</artifactId>
<version>8.0</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>org.apache.cxf</groupId>
<artifactId>cxf-rt-rs-mp-client</artifactId>
<version>3.3.1</version>
<scope>test</scope>
</dependency>
</dependencies>