### Question:
ThriftKeyAsyncClientImp extends ThriftBalancerAsyncClient<I, T> implements ThriftKeyAsyncClient<K, I> { @Override public <R> CompletableFuture<R> execOnQuorum( K key, Class<R> resultType, ThriftAsyncFunction<I, ?> function ) throws NoSuchElementException, ThriftConnectionException { try { Stream<CompletableFuture<R>> futures = keyBalancer.getQuorum(key) .map(status -> status.getClient().execAsync( resultType, function, status.isWorking() ? getMaxWaitMillis() : 0 )); return ThriftUtils.firstSuccess(futures); } catch (NoSuchElementException ex) { throw new NoSuchElementException( "No nodes available. Failed nodes: " + balancer.getFailedNodes().collect(Collectors.toList()) ); } } ThriftKeyAsyncClientImp(
            ThriftKeyLoadBalancer<K, I, ThriftPoolAsyncClient<I, T>> balancer,
            ThriftBalancerConfig config
    ); @Override CompletableFuture<R> execOnKey(
            K key,
            Class<R> resultType,
            ThriftAsyncFunction<I, ?> function
    ); @Override CompletableFuture<R> execOnQuorum(
            K key,
            Class<R> resultType,
            ThriftAsyncFunction<I, ?> function
    );  }### Answer:
@Test(groups = "unit") public void execOnQuorum() throws Exception { CompletableFuture<Long> future = client.execOnQuorum( "TEst", Long.class, function ); assertFalse(future.isDone()); futures.get(0).completeExceptionally(new RuntimeException("Test ex1")); assertFalse(future.isDone()); futures.get(1).complete(345L); assertEquals(future.get(0, TimeUnit.MILLISECONDS), (Object)345L); }
@Test(groups = "unit") public void execOnQuorumFail() throws Exception { CompletableFuture<Long> future = client.execOnQuorum( "TEst", Long.class, function ); assertFalse(future.isDone()); futures.get(0).completeExceptionally(new RuntimeException("Test ex1")); assertFalse(future.isDone()); futures.get(1).completeExceptionally(new RuntimeException("Test ex2")); try { future.get(0, TimeUnit.MILLISECONDS); fail("Not throw"); } catch (ExecutionException ex) { assertTrue(ex.getCause().getMessage().startsWith("Test ex")); } }