0

I have this test case:

TestClient

@RunWith(EasyMockRunner.class)
public class TestClient extends EasyMockSupport {

    @TestSubject
    private final IClient client = new Client();

    @Mock
    private HttpClient httpClient;

    @Mock
    private HttpUriRequest request;
    @Mock
    private HttpResponse response;

    @Test
    public void testExecute() throws ClientProtocolException, IOException {
        expect(httpClient.execute(request)).andReturn(response);
        replayAll();
        httpClient.execute(request);
        client.execute(request);
        verifyAll();
    }
}

Client

public class Client implements IClient {

    private final HttpClient httpClient;

    public Client() {
        httpClient = createDefaultClient();
    }

    private HttpClient createDefaultClient() {
        return HttpClientBuilder.create()
                .build();
    }

    @Override
    public HttpResponse execute(final HttpUriRequest request)
            throws IOException {
        return httpClient.execute(request);
    }

}

When I run it I get this error:

Unexpected method call HttpUriRequest.getURI()

Normally the created will not call this method.

Why I get this error? Why it require me to define a result for getURI method?

Hunsu
  • 3,281
  • 7
  • 29
  • 64

3 Answers3

2

You must remove final from

private final HttpClient httpClient;

Otherwise EasyMock cannot overwrite your httpClient with its own mocked instance. Of course better still would be to directly use dependency injection, but that's tangential to your actual issue.

You can use reflection as a workaround; but dear me no...


Original answer:

Posting a full stack trace, and relevant parts of your Client class would help us debug this with you. You mention that:

in client.execute(request) I do httpClient.execute(request).

But (at least in the code you've posted) nowhere does client get a reference to the mocked httpClient instance. Does your Client class perhaps construct it's own HttpClient instance, and make requests against that instead of your mock?

If so, your Client should follow the dependency injection pattern and pass in an HttpClient instance at construction, rather than construct one internally.

Another possibility is that your Client.execute() method is calling request.getURI() at some point, in which case you simply need to expect() a call to request.getURI().

Community
  • 1
  • 1
dimo414
  • 47,227
  • 18
  • 148
  • 244
  • The mocked `httpClient` will be injected by EasyMock (that why I use `TestSubject` annotation). I agree it is not visible if we don't know the framework. – Hunsu May 15 '15 at 17:49
  • @user230137 please include your `Client` code so we can see what it's doing. If you make a call to `new HttpClient()` anywhere in `Client` that will be used even though EasyMock is injecting. – dimo414 May 15 '15 at 17:53
  • I added the client code. When removing final it works but perhaps there's a solution to that. – Hunsu May 15 '15 at 17:57
  • And even if I call `request.getURI()` in my `Client.execute()` it should work because it will not call it as the method is mocked. – Hunsu May 15 '15 at 17:59
  • @user230137 Yes, the issue is your `final httpClient` instance variable. Updated answer. – dimo414 May 15 '15 at 18:33
0

I suspect that inside of the method client.execute(request) there is a request.getURI() statement (or buried deeply in called methods). Easy Mock needs to know the response to give when this method is called.

Brett Walker
  • 3,566
  • 1
  • 18
  • 36
  • in `client.execute(request)` I do `httpClient.execute(request)`. Why EasyMock needs to know the response for `getURI` method? I have created an expectation for method. It isn't the point of mocking? – Hunsu May 15 '15 at 15:08
  • @user230137 it would help if you posted the contents of `Client.execute()`; otherwise we can only speculate. – dimo414 May 15 '15 at 17:18
0

I suspect the problem is the call of httpClient.execute(request);. Try to remove it. You already setup a expectation for the httpClient via expect(httpClient.execute(request)).andReturn(response);.

@Test
public void testExecute() throws ClientProtocolException, IOException {
    expect(httpClient.execute(request)).andReturn(response);
    replayAll();
    client.execute(request);
    verifyAll();
}
eee
  • 3,241
  • 1
  • 17
  • 34
  • No it's not that. EasyMock failed to inject my mock as the field is final but failed silently – Hunsu May 15 '15 at 17:13