Skip to content

Commit

Permalink
[mock] verifyTimes with RequestKey parameter (#1517)
Browse files Browse the repository at this point in the history
* [mock] verifyTimes with RequestKey parameter

* Re-implement verify* methods with RequestKey parameters and stricter equals check for headers and body

Co-authored-by: Marvin Froeder <velo@users.noreply.github.com>
  • Loading branch information
vitalijr2 and velo authored Oct 14, 2021
1 parent b2adb39 commit c2503e6
Show file tree
Hide file tree
Showing 2 changed files with 115 additions and 13 deletions.
44 changes: 43 additions & 1 deletion mock/src/main/java/feign/mock/MockClient.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2012-2020 The Feign Authors
* Copyright 2012-2021 The Feign Authors
*
* <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
Expand Down Expand Up @@ -227,6 +227,10 @@ public Request verifyOne(HttpMethod method, String url) {
return verifyTimes(method, url, 1).get(0);
}

public Request verifyOne(RequestKey requestKey) {
return verifyTimes(requestKey, 1).get(0);
}

public List<Request> verifyTimes(final HttpMethod method, final String url, final int times) {
if (times < 0) {
throw new IllegalArgumentException("times must be a non negative number");
Expand All @@ -253,13 +257,51 @@ public List<Request> verifyTimes(final HttpMethod method, final String url, fina
return result;
}

public List<Request> verifyTimes(RequestKey requestKey, final int times) {
if (times < 0) {
throw new IllegalArgumentException("times must be a non negative number");
}

if (times == 0) {
verifyNever(requestKey);
return Collections.emptyList();
}

List<Request> result = null;
for (Map.Entry<RequestKey, List<Request>> request : requests.entrySet()) {
if (request.getKey().equalsExtended(requestKey)) {
result = request.getValue();
}
}
if (result == null) {
throw new VerificationAssertionError(
"Wanted: '%s' but never invoked! Got: %s", requestKey, requests.keySet());
}

if (result.size() != times) {
throw new VerificationAssertionError(
"Wanted: '%s' to be invoked: '%s' times but got: '%s'!",
requestKey, times, result.size());
}

return result;
}

public void verifyNever(HttpMethod method, String url) {
RequestKey requestKey = RequestKey.builder(method, url).build();
if (requests.containsKey(requestKey)) {
throw new VerificationAssertionError("Do not wanted: '%s' but was invoked!", requestKey);
}
}

public void verifyNever(RequestKey requestKey) {
for (RequestKey recorderRequestKey : requests.keySet()) {
if (recorderRequestKey.equalsExtended(requestKey)) {
throw new VerificationAssertionError("Do not wanted: '%s' but was invoked!", requestKey);
}
}
}

/**
* To be called in an &#64;After method:
*
Expand Down
84 changes: 72 additions & 12 deletions mock/src/test/java/feign/mock/MockClientTest.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/**
* Copyright 2012-2020 The Feign Authors
* Copyright 2012-2021 The Feign Authors
*
* <p>Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file
* except in compliance with the License. You may obtain a copy of the License at
Expand All @@ -13,6 +13,7 @@
*/
package feign.mock;

import static feign.Util.UTF_8;
import static feign.Util.toByteArray;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.containsString;
Expand All @@ -21,13 +22,7 @@
import static org.hamcrest.Matchers.notNullValue;
import static org.junit.Assert.fail;

import feign.Body;
import feign.Feign;
import feign.FeignException;
import feign.Param;
import feign.Request;
import feign.RequestLine;
import feign.Response;
import feign.*;
import feign.codec.DecodeException;
import feign.codec.Decoder;
import feign.gson.GsonDecoder;
Expand Down Expand Up @@ -58,6 +53,7 @@ List<Contributor> contributors(
List<Contributor> patchContributors(@Param("owner") String owner, @Param("repo") String repo);

@RequestLine("POST /repos/{owner}/{repo}/contributors")
@Headers({"Content-Type: application/json"})
@Body("%7B\"login\":\"{login}\",\"type\":\"{type}\"%7D")
Contributor create(
@Param("owner") String owner,
Expand Down Expand Up @@ -97,6 +93,16 @@ public Object decode(Response response, Type type)
public void setup() throws IOException {
try (InputStream input = getClass().getResourceAsStream("/fixtures/contributors.json")) {
byte[] data = toByteArray(input);
RequestKey postContributorKey =
RequestKey.builder(HttpMethod.POST, "/repos/netflix/feign/contributors")
.charset(UTF_8)
.headers(
RequestHeaders.builder()
.add("Content-Length", "55")
.add("Content-Type", "application/json")
.build())
.body("{\"login\":\"velo_at_github\",\"type\":\"preposterous hacker\"}")
.build();
mockClient = new MockClient();
github =
Feign.builder()
Expand All @@ -109,10 +115,7 @@ public void setup() throws IOException {
HttpMethod.GET,
"/repos/netflix/feign/contributors?client_id=7 7",
new ByteArrayInputStream(data))
.ok(
HttpMethod.POST,
"/repos/netflix/feign/contributors",
"{\"login\":\"velo\",\"contributions\":0}")
.ok(postContributorKey, "{\"login\":\"velo\",\"contributions\":0}")
.noContent(HttpMethod.PATCH, "/repos/velo/feign-mock/contributors")
.add(
HttpMethod.GET,
Expand Down Expand Up @@ -173,6 +176,16 @@ public void paramsEncoding() {

@Test
public void verifyInvocation() {
RequestKey testRequestKey =
RequestKey.builder(HttpMethod.POST, "/repos/netflix/feign/contributors")
.headers(
RequestHeaders.builder()
.add("Content-Length", "55")
.add("Content-Type", "application/json")
.build())
.body("{\"login\":\"velo_at_github\",\"type\":\"preposterous hacker\"}")
.build();

Contributor contribution =
github.create("netflix", "feign", "velo_at_github", "preposterous hacker");
// making sure it received a proper response
Expand All @@ -183,7 +196,10 @@ public void verifyInvocation() {
List<Request> results =
mockClient.verifyTimes(HttpMethod.POST, "/repos/netflix/feign/contributors", 1);
assertThat(results, hasSize(1));
results = mockClient.verifyTimes(testRequestKey, 1);
assertThat(results, hasSize(1));

assertThat(mockClient.verifyOne(testRequestKey).body(), notNullValue());
byte[] body = mockClient.verifyOne(HttpMethod.POST, "/repos/netflix/feign/contributors").body();
assertThat(body, notNullValue());

Expand All @@ -196,9 +212,53 @@ public void verifyInvocation() {

@Test
public void verifyNone() {
RequestKey testRequestKey;
github.create("netflix", "feign", "velo_at_github", "preposterous hacker");
mockClient.verifyTimes(HttpMethod.POST, "/repos/netflix/feign/contributors", 1);

testRequestKey =
RequestKey.builder(HttpMethod.POST, "/repos/netflix/feign/contributors")
.charset(UTF_8)
.headers(
RequestHeaders.builder()
.add("Content-Length", "55")
.add("Content-Type", "application/json")
.build())
// body is not equal
.body("{\"login\":\"velo[at]github\",\"type\":\"preposterous hacker\"}")
.build();
try {
mockClient.verifyOne(testRequestKey);
fail();
} catch (VerificationAssertionError e) {
assertThat(e.getMessage(), containsString("Wanted"));
assertThat(e.getMessage(), containsString("POST"));
assertThat(e.getMessage(), containsString("/repos/netflix/feign/contributors"));
}
mockClient.verifyNever(testRequestKey);

testRequestKey =
RequestKey.builder(HttpMethod.POST, "/repos/netflix/feign/contributors")
.charset(UTF_8)
.headers(
RequestHeaders.builder()
.add("Content-Length", "55")
.add("Content-Type", "application/json")
// headers are not equal
.add("X-Header", "qwerty")
.build())
.body("{\"login\":\"velo_at_github\",\"type\":\"preposterous hacker\"}")
.build();
try {
mockClient.verifyOne(testRequestKey);
fail();
} catch (VerificationAssertionError e) {
assertThat(e.getMessage(), containsString("Wanted"));
assertThat(e.getMessage(), containsString("POST"));
assertThat(e.getMessage(), containsString("/repos/netflix/feign/contributors"));
}
mockClient.verifyNever(testRequestKey);

try {
mockClient.verifyTimes(HttpMethod.POST, "/repos/netflix/feign/contributors", 0);
fail();
Expand Down

0 comments on commit c2503e6

Please sign in to comment.