Skip to content

🐛 bug(feign-14): Http2ClientTest depends on external service nghttp2.org/httpbin and fails the build when it is down #3483

Description

@yvasyliev

Description

The test class java11/src/test/java/feign/http2client/test/Http2ClientTest.java contains four tests that make real
HTTP calls to https://nghttp2.org/httpbin/:

  • patch()
  • noResponseBodyForPatch()
  • getWithRequestBody()
  • deleteWithRequestBody()

These tests are guarded by assumeTrue(HTTPBIN_REACHABLE, ...), but the reachability check only performs a DNS lookup (
InetAddress.getByName("nghttp2.org")). When the DNS resolves but the HTTP service itself is down or unresponsive (
e.g., the https://nghttp2.org/httpbin/patch endpoint returns 504 Gateway Timeout, or the server is timing out), the
assumeTrue passes but the subsequent HTTP requests either fail or hang indefinitely — causing the entire project
build to fail or freeze
.

Image

Steps to Reproduce

  1. Run ./mvnw -Pdev clean license:format install (or ./mvnw -Pdev -pl java11 clean license:format install)
  2. Observe that https://nghttp2.org/httpbin/patch is unresponsive or returning errors
  3. Build fails with connection/timeout/HTTP error exceptions from the four tests above, or hangs indefinitely (e.g.,
    when the endpoint returns 504 Gateway Timeout, the test freezes rather than failing fast)

Expected Behavior

Tests that depend on external services should either:

  • Be skipped reliably when the service is unavailable (e.g., check HTTP connectivity, not just DNS), or
  • Use MockWebServer (already available as a test dependency) instead of a live external service

Actual Behavior

The DNS-based reachability check passes, but the HTTP requests fail (or hang indefinitely, e.g., on a 504 Gateway
Timeout), causing the entire build to fail or freeze.

Notes

I may look into this later, but not in the near future.

Affected Code

https://github.com/OpenFeign/feign/blob/14.x/java11/src/test/java/feign/http2client/test/Http2ClientTest.java

Lines 43–54 (reachability check), and lines 98–112, 171–188 (the four affected tests).

private static final boolean HTTPBIN_REACHABLE;
static {
boolean reachable = false;
try {
java.net.InetAddress.getByName("nghttp2.org");
reachable = true;
} catch (java.net.UnknownHostException _) {
// ignore
}
HTTPBIN_REACHABLE = reachable;
}

@Override
@Test
public void patch() throws Exception {
assumeTrue(HTTPBIN_REACHABLE, "nghttp2.org is not reachable");
final TestInterface api =
newBuilder().target(TestInterface.class, "https://nghttp2.org/httpbin/");
assertThat(api.patch("")).contains("https://nghttp2.org/httpbin/patch");
}
@Override
@Test
public void noResponseBodyForPatch() {
assumeTrue(HTTPBIN_REACHABLE, "nghttp2.org is not reachable");
final TestInterface api =
newBuilder().target(TestInterface.class, "https://nghttp2.org/httpbin/");
assertThat(api.patch()).contains("https://nghttp2.org/httpbin/patch");
}

@Test
void getWithRequestBody() throws Exception {
assumeTrue(HTTPBIN_REACHABLE, "nghttp2.org is not reachable");
final TestInterface api =
newBuilder().target(TestInterface.class, "https://nghttp2.org/httpbin/");
String result = api.getWithBody();
String expected = "{ \"data\":\"some request body\" }";
JSONAssert.assertEquals(expected, result, false);
}
@Test
void deleteWithRequestBody() throws Exception {
assumeTrue(HTTPBIN_REACHABLE, "nghttp2.org is not reachable");
final TestInterface api =
newBuilder().target(TestInterface.class, "https://nghttp2.org/httpbin/");
String result = api.deleteWithBody();
String expected = "{ \"data\":\"some request body\" }";
JSONAssert.assertEquals(expected, result, false);
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Fields

    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions