@Disabled("FIXME random test failures when building on ubuntu, need to investigate further")
  // @ParameterizedTest
  // @ValueSource(ints = {1, 5, 10, 100, 1000})
  public void cancelRetry(final int expectedTryCount) throws Throwable {
    // Arrange
    final CompletableFuture<Boolean> maximumTryCompleted = new CompletableFuture<>();
    final AtomicInteger actualTryCount = new AtomicInteger();
    final AtomicBoolean isCancelled = new AtomicBoolean(true);

    final int RUNNING_TIME_MILLIS = 100;
    final ExecutorService execs = Executors.newSingleThreadExecutor();
    final AsyncClient<Void> clientMock =
        (request, options, requestContext) ->
            CompletableFuture.supplyAsync(
                () -> {
                  final int tryCount = actualTryCount.addAndGet(1);
                  if (tryCount < expectedTryCount) {
                    throw new CompletionException(new IOException());
                  }

                  if (tryCount > expectedTryCount) {
                    isCancelled.set(false);
                    throw new CompletionException(new IOException());
                  }

                  maximumTryCompleted.complete(true);
                  try {
                    Thread.sleep(RUNNING_TIME_MILLIS);
                    throw new IOException();
                  } catch (Throwable e) {
                    throw new CompletionException(e);
                  }
                },
                execs);
    final TestInterfaceAsync sut =
        AsyncFeign.<Void>builder()
            .client(clientMock)
            .retryer(new Retryer.Default(0, Long.MAX_VALUE, expectedTryCount * 2))
            .target(TestInterfaceAsync.class, "http://localhost:" + server.getPort());

    // Act
    final CompletableFuture<String> actual = sut.post();
    maximumTryCompleted.join();
    actual.cancel(true);
    Thread.sleep(RUNNING_TIME_MILLIS * 5);

    // Assert
    assertThat(actualTryCount.get()).isEqualTo(expectedTryCount);
    assertThat(isCancelled.get()).isTrue();
    execs.shutdown();
  }
when you must parse a 2xx status to determine if the operation succeeded or not.
core/src/test/java/feign/AsyncFeignTest.java