Search code examples
junitjava-8mockingmockitoresteasy

Mocking a post request using Mockito raises javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request


I'm totally new to Mockito and I need to mock a post request so that I can test a client alone. However, no matter what I do I get the RESTEASY004655: Unable to invoke request exception. This is the simplified version of what I have so far. I have the class TestClassA which sends a post request to an api as follows:

import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;

import javax.ws.rs.client.Entity;
import javax.ws.rs.core.Response;

import org.jboss.resteasy.client.jaxrs.ResteasyClient;
import org.jboss.resteasy.client.jaxrs.ResteasyClientBuilder;
import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;

import com.fasterxml.jackson.databind.ObjectMapper;

public class TestClassA {

    public int moveActual(String path) throws IOException {

        Response resp = null;
        String newHome = "0" ;
        ResteasyClient client = new ResteasyClientBuilder().build();
        ResteasyWebTarget callTarget = client.target(path) ;

        Map<String, Object> request = new HashMap<>();
        request.put("operation", "dislocation");
        request.put("direction", "right");
        request.put("amount", "2");
        request.put("unit", "metric");
        String payload = new ObjectMapper().writeValueAsString(request);

        resp = callTarget.request().post(Entity.entity(payload, "application/json"));
        String outcome = resp.readEntity(String.class);
        ObjectMapper outcomeMapper = new ObjectMapper();
        @SuppressWarnings("unchecked")
        Map<String, Object> finalResponse = (Map<String, Object>) outcomeMapper.readValue(outcome, Map.class);

        if (finalResponse != null) {
            newHome = (String) finalResponse.get("coordinate");
        }
        return Integer.parseInt(newHome) ;
    }
}

I try to mock the post request using the mockito test bellow:

import static org.junit.Assert.assertEquals;

import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Answers;
import org.mockito.ArgumentMatchers;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.junit.MockitoJUnitRunner;
import static org.mockito.BDDMockito.given;

import java.util.HashMap;
import java.util.Map;

import org.jboss.resteasy.client.jaxrs.ResteasyWebTarget;

import javax.ws.rs.client.Entity;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.Response.Status;
import externalTests.TestClassA;

@RunWith(MockitoJUnitRunner.class)
public class DispositionMockTest {

    @Mock(answer = Answers.RETURNS_DEEP_STUBS)
    ResteasyWebTarget targetMock;

    @InjectMocks
    TestClassA classA;


    @Test
    public void dispositionTest() throws Exception {
        // Given
        Map<String, Integer> outcomeMap = new HashMap<String, Integer>() ;
        outcomeMap.put("coordinate", 4) ;
        Response resp = Response.status(Status.OK).type(MediaType.APPLICATION_JSON).entity(outcomeMap).build() ;

        //  Builder req = DispositionMockTest.fakeRequest() ;
        //  given(req.post(ArgumentMatchers.any(Entity.class))).willReturn(fakeRequest()) ;

        given(targetMock.request().post(ArgumentMatchers.any(Entity.class))).willReturn(resp) ;

        // When
        int result = classA.moveActual("url to what has to run") ;

        // Then
        assertEquals(4, result);
    }
}

I also tried to mock the request method using the two commented out lines in the test and have it return more or less fake Builder from the method bellow.

public static Builder fakeRequest() {
    ResteasyClient httpClient = new ResteasyClientBuilder().build();
    ResteasyWebTarget target = httpClient.target("");
    Builder req = target.request() ;
    return req ;
}

But I keep getting this exception.

javax.ws.rs.ProcessingException: RESTEASY004655: Unable to invoke request: org.apache.http.client.ClientProtocolException
    at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:325)
    at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:443)
    at org.jboss.resteasy.client.jaxrs.internal.ClientInvocation.invoke(ClientInvocation.java:62)
    at org.jboss.resteasy.client.jaxrs.internal.ClientInvocationBuilder.post(ClientInvocationBuilder.java:219)
    at externalTests.TestClassA.moveActual(TestClassA.java:33)
    at externalTests.DispositionMockTest.dispositionTest(DispositionMockTest.java:60)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:50)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.mockito.internal.runners.DefaultInternalRunner$1$1.evaluate(DefaultInternalRunner.java:46)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:290)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:71)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:58)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:268)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
    at org.mockito.internal.runners.DefaultInternalRunner$1.run(DefaultInternalRunner.java:77)
    at org.mockito.internal.runners.DefaultInternalRunner.run(DefaultInternalRunner.java:83)
    at org.mockito.internal.runners.StrictRunner.run(StrictRunner.java:39)
    at org.mockito.junit.MockitoJUnitRunner.run(MockitoJUnitRunner.java:163)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:89)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:41)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:542)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:770)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:464)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:210)
Caused by: org.apache.http.client.ClientProtocolException
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:187)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:83)
    at org.apache.http.impl.client.CloseableHttpClient.execute(CloseableHttpClient.java:56)
    at org.jboss.resteasy.client.jaxrs.engines.ApacheHttpClient4Engine.invoke(ApacheHttpClient4Engine.java:320)
    ... 33 more
Caused by: org.apache.http.ProtocolException: Target host is not specified
    at org.apache.http.impl.conn.DefaultRoutePlanner.determineRoute(DefaultRoutePlanner.java:71)
    at org.apache.http.impl.client.InternalHttpClient.determineRoute(InternalHttpClient.java:125)
    at org.apache.http.impl.client.InternalHttpClient.doExecute(InternalHttpClient.java:184)
    ... 36 more

I tried many possible solutions I found online but I can't get anything to work. If anyone knows how I can mock a post request I would be truly thankful to learn from them.


Solution

  • For whoever may need it. I couldn't find a way to get it done using mockito. I had to move to wiremock. In wiremock you just record a successful transaction, create a wiremock server object, and have it mock the recorded behavior. Much easier and faster.