HystrixCommand extends AbstractCommand<R> implements HystrixExecutable<R>, HystrixInvokableInfo<R>, HystrixObservable<R> { public R execute() { try { return queue().get(); } catch (Exception e) { throw Exceptions.sneakyThrow(decomposeException(e)); } } protected  HystrixCommand(HystrixCommandGroupKey group); protected  HystrixCommand(HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool); protected  HystrixCommand(HystrixCommandGroupKey group, int executionIsolationThreadTimeoutInMilliseconds); protected  HystrixCommand(HystrixCommandGroupKey group, HystrixThreadPoolKey threadPool, int executionIsolationThreadTimeoutInMilliseconds); protected  HystrixCommand(Setter setter);   HystrixCommand(HystrixCommandGroupKey group, HystrixCommandKey key, HystrixThreadPoolKey threadPoolKey, HystrixCircuitBreaker circuitBreaker, HystrixThreadPool threadPool,
            HystrixCommandProperties.Setter commandPropertiesDefaults, HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults,
            HystrixCommandMetrics metrics, TryableSemaphore fallbackSemaphore, TryableSemaphore executionSemaphore,
            HystrixPropertiesStrategy propertiesStrategy, HystrixCommandExecutionHook executionHook); R execute(); Future<R> queue();  }
@Test public void testExecutionSuccess() { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.SUCCESS); assertEquals(FlexibleTestHystrixCommand.EXECUTE_VALUE, command.execute()); assertEquals(null, command.getFailedExecutionException()); assertNull(command.getExecutionException()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isSuccessfulExecution()); assertCommandExecutionEvents(command, HystrixEventType.SUCCESS); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); System.out.println("ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); assertSaneHystrixRequestLog(1); }
@Test public void testExecutionMultipleTimes() { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.SUCCESS); assertFalse(command.isExecutionComplete()); assertEquals(FlexibleTestHystrixCommand.EXECUTE_VALUE, command.execute()); assertTrue(command.isExecutionComplete()); assertTrue(command.isExecutedInThread()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isSuccessfulExecution()); assertNull(command.getExecutionException()); try { command.execute(); fail("we should not allow this ... it breaks the state of request logs"); } catch (HystrixRuntimeException e) { e.printStackTrace(); } assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); assertCommandExecutionEvents(command, HystrixEventType.SUCCESS); }
@Test public void testExecutionHystrixFailureWithNoFallback() { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.HYSTRIX_FAILURE, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED); try { command.execute(); fail("we shouldn't get here"); } catch (HystrixRuntimeException e) { e.printStackTrace(); assertNotNull(e.getFallbackException()); assertNotNull(e.getImplementingClass()); } assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_MISSING); assertNotNull(command.getExecutionException()); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testExecutionFailureWithNoFallback() { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.FAILURE, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED); try { command.execute(); fail("we shouldn't get here"); } catch (HystrixRuntimeException e) { e.printStackTrace(); assertNotNull(e.getFallbackException()); assertNotNull(e.getImplementingClass()); } assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_MISSING); assertNotNull(command.getExecutionException()); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testNotWrappedExceptionWithNoFallback() { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.NOT_WRAPPED_FAILURE, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED); try { command.execute(); fail("we shouldn't get here"); } catch (HystrixRuntimeException e) { e.printStackTrace(); fail("we shouldn't get a HystrixRuntimeException"); } catch (RuntimeException e) { assertTrue(e instanceof NotWrappedByHystrixTestRuntimeException); } assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_MISSING); assertNotNull(command.getExecutionException()); assertTrue(command.getExecutionException() instanceof NotWrappedByHystrixTestRuntimeException); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testNotWrappedBadRequestWithNoFallback() { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.BAD_REQUEST_NOT_WRAPPED, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED); try { command.execute(); fail("we shouldn't get here"); } catch (HystrixRuntimeException e) { e.printStackTrace(); fail("we shouldn't get a HystrixRuntimeException"); } catch (RuntimeException e) { assertTrue(e instanceof NotWrappedByHystrixTestRuntimeException); } assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.getEventCounts().contains(HystrixEventType.BAD_REQUEST)); assertCommandExecutionEvents(command, HystrixEventType.BAD_REQUEST); assertNotNull(command.getExecutionException()); assertTrue(command.getExecutionException() instanceof HystrixBadRequestException); assertTrue(command.getExecutionException().getCause() instanceof NotWrappedByHystrixTestRuntimeException); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testNotWrappedBadRequestWithFallback() throws Exception { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.BAD_REQUEST_NOT_WRAPPED, AbstractTestHystrixCommand.FallbackResult.SUCCESS); try { command.execute(); fail("we shouldn't get here"); } catch (HystrixRuntimeException e) { e.printStackTrace(); fail("we shouldn't get a HystrixRuntimeException"); } catch (RuntimeException e) { assertTrue(e instanceof NotWrappedByHystrixTestRuntimeException); } assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.getEventCounts().contains(HystrixEventType.BAD_REQUEST)); assertCommandExecutionEvents(command, HystrixEventType.BAD_REQUEST); assertNotNull(command.getExecutionException()); assertTrue(command.getExecutionException() instanceof HystrixBadRequestException); assertTrue(command.getExecutionException().getCause() instanceof NotWrappedByHystrixTestRuntimeException); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testExecutionFailureWithFallback() { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.FAILURE, AbstractTestHystrixCommand.FallbackResult.SUCCESS); assertEquals(FlexibleTestHystrixCommand.FALLBACK_VALUE, command.execute()); assertEquals("Execution Failure for TestHystrixCommand", command.getFailedExecutionException().getMessage()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS); assertNotNull(command.getExecutionException()); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testNotWrappedExceptionWithFallback() { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.NOT_WRAPPED_FAILURE, AbstractTestHystrixCommand.FallbackResult.SUCCESS); assertEquals(FlexibleTestHystrixCommand.FALLBACK_VALUE, command.execute()); assertEquals("Raw exception for TestHystrixCommand", command.getFailedExecutionException().getMessage()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS); assertNotNull(command.getExecutionException()); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testExecutionFailureWithFallbackFailure() { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.FAILURE, AbstractTestHystrixCommand.FallbackResult.FAILURE); try { command.execute(); fail("we shouldn't get here"); } catch (HystrixRuntimeException e) { System.out.println("------------------------------------------------"); e.printStackTrace(); System.out.println("------------------------------------------------"); assertNotNull(e.getFallbackException()); } assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_FAILURE); assertNotNull(command.getExecutionException()); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testCircuitBreakerReportsOpenIfForcedOpen() { HystrixCommand<Boolean> cmd = new HystrixCommand<Boolean>(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GROUP")).andCommandPropertiesDefaults(new HystrixCommandProperties.Setter().withCircuitBreakerForceOpen(true))) { @Override protected Boolean run() throws Exception { return true; } @Override protected Boolean getFallback() { return false; } }; assertFalse(cmd.execute()); System.out.println("RESULT : " + cmd.getExecutionEvents()); assertTrue(cmd.isCircuitBreakerOpen()); }
@Test public void testCircuitBreakerReportsClosedIfForcedClosed() { HystrixCommand<Boolean> cmd = new HystrixCommand<Boolean>(HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("GROUP")).andCommandPropertiesDefaults( new HystrixCommandProperties.Setter().withCircuitBreakerForceOpen(false).withCircuitBreakerForceClosed(true))) { @Override protected Boolean run() throws Exception { return true; } @Override protected Boolean getFallback() { return false; } }; assertTrue(cmd.execute()); System.out.println("RESULT : " + cmd.getExecutionEvents()); assertFalse(cmd.isCircuitBreakerOpen()); }
@Test public void testCircuitBreakerAcrossMultipleCommandsButSameCircuitBreaker() throws InterruptedException { HystrixCommandKey key = HystrixCommandKey.Factory.asKey("SharedCircuitBreaker"); TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(key); TestHystrixCommand<Integer> attempt1 = getSharedCircuitBreakerCommand(key, ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.FallbackResult.SUCCESS, circuitBreaker); System.out.println("COMMAND KEY (from cmd): " + attempt1.commandKey.name()); attempt1.execute(); Thread.sleep(100); assertTrue(attempt1.isResponseFromFallback()); assertFalse(attempt1.isCircuitBreakerOpen()); assertFalse(attempt1.isResponseShortCircuited()); TestHystrixCommand<Integer> attempt2 = getSharedCircuitBreakerCommand(key, ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.FallbackResult.SUCCESS, circuitBreaker); attempt2.execute(); Thread.sleep(100); assertTrue(attempt2.isFailedExecution()); assertTrue(attempt2.isResponseFromFallback()); assertFalse(attempt2.isCircuitBreakerOpen()); assertFalse(attempt2.isResponseShortCircuited()); TestHystrixCommand<Integer> attempt3 = getSharedCircuitBreakerCommand(key, ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.FallbackResult.SUCCESS, circuitBreaker); attempt3.execute(); Thread.sleep(100); assertTrue(attempt3.isFailedExecution()); assertTrue(attempt3.isResponseFromFallback()); assertFalse(attempt3.isResponseShortCircuited()); assertTrue(attempt3.isCircuitBreakerOpen()); TestHystrixCommand<Integer> attempt4 = getSharedCircuitBreakerCommand(key, ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.FallbackResult.SUCCESS, circuitBreaker); attempt4.execute(); Thread.sleep(100); assertTrue(attempt4.isResponseFromFallback()); assertTrue(attempt4.isResponseShortCircuited()); assertTrue(attempt4.isCircuitBreakerOpen()); assertSaneHystrixRequestLog(4); assertCommandExecutionEvents(attempt1, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS); assertCommandExecutionEvents(attempt2, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS); assertCommandExecutionEvents(attempt3, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS); assertCommandExecutionEvents(attempt4, HystrixEventType.SHORT_CIRCUITED, HystrixEventType.FALLBACK_SUCCESS); }
@Test public void testExecutionSuccessWithCircuitBreakerDisabled() { TestHystrixCommand<Integer> command = getCircuitBreakerDisabledCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.SUCCESS); assertEquals(FlexibleTestHystrixCommand.EXECUTE_VALUE, command.execute()); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); assertCommandExecutionEvents(command, HystrixEventType.SUCCESS); }
@Test public void testExecutionTimeoutWithNoFallback() { TestHystrixCommand<Integer> command = getLatentCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.SUCCESS, 200, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED, 50); try { command.execute(); fail("we shouldn't get here"); } catch (Exception e) { if (e instanceof HystrixRuntimeException) { HystrixRuntimeException de = (HystrixRuntimeException) e; assertNotNull(de.getFallbackException()); assertTrue(de.getFallbackException() instanceof UnsupportedOperationException); assertNotNull(de.getImplementingClass()); assertNotNull(de.getCause()); assertTrue(de.getCause() instanceof TimeoutException); } else { fail("the exception should be HystrixRuntimeException"); } } assertTrue("Execution Time is: " + command.getExecutionTimeInMilliseconds(), command.getExecutionTimeInMilliseconds() >= 50); assertTrue(command.isResponseTimedOut()); assertFalse(command.isResponseFromFallback()); assertFalse(command.isResponseRejected()); assertCommandExecutionEvents(command, HystrixEventType.TIMEOUT, HystrixEventType.FALLBACK_MISSING); assertNotNull(command.getExecutionException()); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testExecutionTimeoutWithFallback() { TestHystrixCommand<Integer> command = getLatentCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.SUCCESS, 200, AbstractTestHystrixCommand.FallbackResult.SUCCESS, 50); assertEquals(FlexibleTestHystrixCommand.FALLBACK_VALUE, command.execute()); assertTrue("Execution Time is: " + command.getExecutionTimeInMilliseconds(), command.getExecutionTimeInMilliseconds() >= 50); assertFalse(command.isCircuitBreakerOpen()); assertFalse(command.isResponseShortCircuited()); assertTrue(command.isResponseTimedOut()); assertTrue(command.isResponseFromFallback()); assertCommandExecutionEvents(command, HystrixEventType.TIMEOUT, HystrixEventType.FALLBACK_SUCCESS); assertNotNull(command.getExecutionException()); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testExecutionTimeoutFallbackFailure() { TestHystrixCommand<Integer> command = getLatentCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.SUCCESS, 200, AbstractTestHystrixCommand.FallbackResult.FAILURE, 50); try { command.execute(); fail("we shouldn't get here"); } catch (Exception e) { if (e instanceof HystrixRuntimeException) { HystrixRuntimeException de = (HystrixRuntimeException) e; assertNotNull(de.getFallbackException()); assertFalse(de.getFallbackException() instanceof UnsupportedOperationException); assertNotNull(de.getImplementingClass()); assertNotNull(de.getCause()); assertTrue(de.getCause() instanceof TimeoutException); } else { fail("the exception should be HystrixRuntimeException"); } } assertNotNull(command.getExecutionException()); assertTrue("Execution Time is: " + command.getExecutionTimeInMilliseconds(), command.getExecutionTimeInMilliseconds() >= 50); assertCommandExecutionEvents(command, HystrixEventType.TIMEOUT, HystrixEventType.FALLBACK_FAILURE); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testCountersOnExecutionTimeout() throws Exception { TestHystrixCommand<Integer> command = getCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.ExecutionResult.SUCCESS, 200, AbstractTestHystrixCommand.FallbackResult.SUCCESS, 50); command.execute(); Thread.sleep(200); assertTrue(command.isResponseFromFallback()); assertFalse(command.isCircuitBreakerOpen()); assertFalse(command.isResponseShortCircuited()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isResponseTimedOut()); assertFalse(command.isSuccessfulExecution()); assertNotNull(command.getExecutionException()); assertCommandExecutionEvents(command, HystrixEventType.TIMEOUT, HystrixEventType.FALLBACK_SUCCESS); assertEquals(0, command.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testShortCircuitFallbackCounter() { TestCircuitBreaker circuitBreaker = new TestCircuitBreaker().setForceShortCircuit(true); KnownFailureTestCommandWithFallback command1 = new KnownFailureTestCommandWithFallback(circuitBreaker); command1.execute(); KnownFailureTestCommandWithFallback command2 = new KnownFailureTestCommandWithFallback(circuitBreaker); command2.execute(); assertTrue(command1.getExecutionTimeInMilliseconds() == -1); assertTrue(command1.isResponseShortCircuited()); assertFalse(command1.isResponseTimedOut()); assertNotNull(command1.getExecutionException()); assertCommandExecutionEvents(command1, HystrixEventType.SHORT_CIRCUITED, HystrixEventType.FALLBACK_SUCCESS); assertCommandExecutionEvents(command2, HystrixEventType.SHORT_CIRCUITED, HystrixEventType.FALLBACK_SUCCESS); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(2); }
@Test public void testRejectedThreadWithFallback() throws InterruptedException { HystrixCommandKey key = HystrixCommandKey.Factory.asKey("Rejection-Fallback"); TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); SingleThreadedPoolWithQueue pool = new SingleThreadedPoolWithQueue(1); TestCommandRejection command1 = new TestCommandRejection(key, circuitBreaker, pool, 500, 600, TestCommandRejection.FALLBACK_SUCCESS); TestCommandRejection command2 = new TestCommandRejection(key, circuitBreaker, pool, 500, 600, TestCommandRejection.FALLBACK_SUCCESS); TestCommandRejection command3 = new TestCommandRejection(key, circuitBreaker, pool, 500, 600, TestCommandRejection.FALLBACK_SUCCESS); Observable<Boolean> result1 = command1.observe(); Observable<Boolean> result2 = command2.observe(); Thread.sleep(100); assertFalse(command3.execute()); assertTrue(command3.isResponseRejected()); assertFalse(command1.isResponseRejected()); assertFalse(command2.isResponseRejected()); assertTrue(command3.isResponseFromFallback()); assertNotNull(command3.getExecutionException()); assertCommandExecutionEvents(command3, HystrixEventType.THREAD_POOL_REJECTED, HystrixEventType.FALLBACK_SUCCESS); Observable.merge(result1, result2).toList().toBlocking().single(); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); System.out.println("ReqLog : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); assertSaneHystrixRequestLog(3); }
@Test public void testDisabledTimeoutWorks() { CommandWithDisabledTimeout cmd = new CommandWithDisabledTimeout(100, 900); boolean result = cmd.execute(); assertEquals(true, result); assertFalse(cmd.isResponseTimedOut()); assertNull(cmd.getExecutionException()); System.out.println("CMD : " + cmd.currentRequestLog.getExecutedCommandsAsString()); assertTrue(cmd.executionResult.getExecutionLatency() >= 900); assertCommandExecutionEvents(cmd, HystrixEventType.SUCCESS); }
@Test public void testExecutionSemaphoreWithExecution() throws Exception { final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); TestSemaphoreCommand command1 = new TestSemaphoreCommand(circuitBreaker, 1, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED); boolean result = command1.execute(); assertFalse(command1.isExecutedInThread()); assertTrue(result); final ArrayBlockingQueue<Boolean> results = new ArrayBlockingQueue<Boolean>(2); final AtomicBoolean exceptionReceived = new AtomicBoolean(); final TryableSemaphore semaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(1)); final TestSemaphoreCommand command2 = new TestSemaphoreCommand(circuitBreaker, semaphore, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED); Runnable r2 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() { @Override public void run() { try { results.add(command2.execute()); } catch (Exception e) { e.printStackTrace(); exceptionReceived.set(true); } } }); final TestSemaphoreCommand command3 = new TestSemaphoreCommand(circuitBreaker, semaphore, 200, TestSemaphoreCommand.RESULT_SUCCESS, TestSemaphoreCommand.FALLBACK_NOT_IMPLEMENTED); Runnable r3 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() { @Override public void run() { try { results.add(command3.execute()); } catch (Exception e) { e.printStackTrace(); exceptionReceived.set(true); } } }); Thread t2 = new Thread(r2); Thread t3 = new Thread(r3); t2.start(); Thread.sleep(50); t3.start(); t2.join(); t3.join(); if (!exceptionReceived.get()) { fail("We expected an exception on the 2nd get"); } assertEquals(1, results.size()); assertTrue(results.contains(Boolean.TRUE)); assertFalse(results.contains(Boolean.FALSE)); assertCommandExecutionEvents(command1, HystrixEventType.SUCCESS); assertCommandExecutionEvents(command2, HystrixEventType.SUCCESS); assertCommandExecutionEvents(command3, HystrixEventType.SEMAPHORE_REJECTED, HystrixEventType.FALLBACK_MISSING); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(3); }
@Test public void testRejectedExecutionSemaphoreWithFallbackViaExecute() throws Exception { final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); final ArrayBlockingQueue<Boolean> results = new ArrayBlockingQueue<Boolean>(2); final AtomicBoolean exceptionReceived = new AtomicBoolean(); final TestSemaphoreCommandWithFallback command1 = new TestSemaphoreCommandWithFallback(circuitBreaker, 1, 200, false); Runnable r1 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() { @Override public void run() { try { results.add(command1.execute()); } catch (Exception e) { e.printStackTrace(); exceptionReceived.set(true); } } }); final TestSemaphoreCommandWithFallback command2 = new TestSemaphoreCommandWithFallback(circuitBreaker, 1, 200, false); Runnable r2 = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() { @Override public void run() { try { results.add(command2.execute()); } catch (Exception e) { e.printStackTrace(); exceptionReceived.set(true); } } }); Thread t1 = new Thread(r1); Thread t2 = new Thread(r2); t1.start(); Thread.sleep(50); t2.start(); t1.join(); t2.join(); if (exceptionReceived.get()) { fail("We should have received a fallback response"); } assertEquals(2, results.size()); assertTrue(results.contains(Boolean.TRUE)); assertTrue(results.contains(Boolean.FALSE)); assertCommandExecutionEvents(command1, HystrixEventType.SUCCESS); assertCommandExecutionEvents(command2, HystrixEventType.SEMAPHORE_REJECTED, HystrixEventType.FALLBACK_SUCCESS); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(2); }
@Test public void testSemaphorePermitsInUse() throws Exception { final TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); final TryableSemaphoreActual sharedSemaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(3)); final CountDownLatch startLatch = new CountDownLatch((sharedSemaphore.numberOfPermits.get() * 2) + 1); final CountDownLatch sharedLatch = new CountDownLatch(1); final AtomicInteger failureCount = new AtomicInteger(); final Runnable sharedSemaphoreRunnable = new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() { public void run() { try { new LatchedSemaphoreCommand("Command-Shared", circuitBreaker, sharedSemaphore, startLatch, sharedLatch).execute(); } catch (Exception e) { startLatch.countDown(); e.printStackTrace(); failureCount.incrementAndGet(); } } }); final int sharedThreadCount = sharedSemaphore.numberOfPermits.get() * 2; final Thread[] sharedSemaphoreThreads = new Thread[sharedThreadCount]; for (int i = 0; i < sharedThreadCount; i++) { sharedSemaphoreThreads[i] = new Thread(sharedSemaphoreRunnable); } final TryableSemaphoreActual isolatedSemaphore = new TryableSemaphoreActual(HystrixProperty.Factory.asProperty(1)); final CountDownLatch isolatedLatch = new CountDownLatch(1); final Thread isolatedThread = new Thread(new HystrixContextRunnable(HystrixPlugins.getInstance().getConcurrencyStrategy(), new Runnable() { public void run() { try { new LatchedSemaphoreCommand("Command-Isolated", circuitBreaker, isolatedSemaphore, startLatch, isolatedLatch).execute(); } catch (Exception e) { startLatch.countDown(); e.printStackTrace(); failureCount.incrementAndGet(); } } })); assertEquals("before threads start, shared semaphore should be unused", 0, sharedSemaphore.getNumberOfPermitsUsed()); assertEquals("before threads start, isolated semaphore should be unused", 0, isolatedSemaphore.getNumberOfPermitsUsed()); for (int i = 0; i < sharedThreadCount; i++) { sharedSemaphoreThreads[i].start(); } isolatedThread.start(); startLatch.await(1000, TimeUnit.MILLISECONDS); assertEquals("immediately after command start, all shared semaphores should be in-use", sharedSemaphore.numberOfPermits.get().longValue(), sharedSemaphore.getNumberOfPermitsUsed()); assertEquals("immediately after command start, isolated semaphore should be in-use", isolatedSemaphore.numberOfPermits.get().longValue(), isolatedSemaphore.getNumberOfPermitsUsed()); sharedLatch.countDown(); isolatedLatch.countDown(); for (int i = 0; i < sharedThreadCount; i++) { sharedSemaphoreThreads[i].join(); } isolatedThread.join(); System.out.println("REQLOG : " + HystrixRequestLog.getCurrentRequest().getExecutedCommandsAsString()); assertEquals("after all threads have finished, no shared semaphores should be in-use", 0, sharedSemaphore.getNumberOfPermitsUsed()); assertEquals("after all threads have finished, isolated semaphore not in-use", 0, isolatedSemaphore.getNumberOfPermitsUsed()); assertEquals("expected some of shared semaphore commands to get rejected", sharedSemaphore.numberOfPermits.get().longValue(), failureCount.get()); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); }
@Test public void testDynamicOwner() { TestHystrixCommand<Boolean> command = new DynamicOwnerTestCommand(InspectableBuilder.CommandGroupForUnitTest.OWNER_ONE); assertEquals(true, command.execute()); assertCommandExecutionEvents(command, HystrixEventType.SUCCESS); }
@Test(expected = IllegalStateException.class) public void testDynamicOwnerFails() { TestHystrixCommand<Boolean> command = new DynamicOwnerTestCommand(null); assertEquals(true, command.execute()); }
@Test public void testDynamicKey() throws Exception { DynamicOwnerAndKeyTestCommand command1 = new DynamicOwnerAndKeyTestCommand(InspectableBuilder.CommandGroupForUnitTest.OWNER_ONE, InspectableBuilder.CommandKeyForUnitTest.KEY_ONE); assertEquals(true, command1.execute()); DynamicOwnerAndKeyTestCommand command2 = new DynamicOwnerAndKeyTestCommand(InspectableBuilder.CommandGroupForUnitTest.OWNER_ONE, InspectableBuilder.CommandKeyForUnitTest.KEY_TWO); assertEquals(true, command2.execute()); assertNotSame(command1.getCircuitBreaker(), command2.getCircuitBreaker()); }
@Test public void testRequestCacheViaExecuteSemaphore1() { TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); SuccessfulCacheableCommandViaSemaphore command1 = new SuccessfulCacheableCommandViaSemaphore(circuitBreaker, true, "A"); SuccessfulCacheableCommandViaSemaphore command2 = new SuccessfulCacheableCommandViaSemaphore(circuitBreaker, true, "B"); SuccessfulCacheableCommandViaSemaphore command3 = new SuccessfulCacheableCommandViaSemaphore(circuitBreaker, true, "A"); assertFalse(command1.isCommandRunningInThread()); String f1 = command1.execute(); String f2 = command2.execute(); String f3 = command3.execute(); assertEquals("A", f1); assertEquals("B", f2); assertEquals("A", f3); assertTrue(command1.executed); assertTrue(command2.executed); assertFalse(command3.executed); assertCommandExecutionEvents(command1, HystrixEventType.SUCCESS); assertCommandExecutionEvents(command2, HystrixEventType.SUCCESS); assertCommandExecutionEvents(command3, HystrixEventType.SUCCESS, HystrixEventType.RESPONSE_FROM_CACHE); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(3); }
@Test public void testNoRequestCacheViaExecuteSemaphore1() { TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); SuccessfulCacheableCommandViaSemaphore command1 = new SuccessfulCacheableCommandViaSemaphore(circuitBreaker, false, "A"); SuccessfulCacheableCommandViaSemaphore command2 = new SuccessfulCacheableCommandViaSemaphore(circuitBreaker, false, "B"); SuccessfulCacheableCommandViaSemaphore command3 = new SuccessfulCacheableCommandViaSemaphore(circuitBreaker, false, "A"); assertFalse(command1.isCommandRunningInThread()); String f1 = command1.execute(); String f2 = command2.execute(); String f3 = command3.execute(); assertEquals("A", f1); assertEquals("B", f2); assertEquals("A", f3); assertTrue(command1.executed); assertTrue(command2.executed); assertTrue(command3.executed); assertCommandExecutionEvents(command1, HystrixEventType.SUCCESS); assertCommandExecutionEvents(command2, HystrixEventType.SUCCESS); assertCommandExecutionEvents(command3, HystrixEventType.SUCCESS); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(3); }
@Test public void testBadRequestExceptionViaExecuteInThread() { TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); BadRequestCommand command1 = null; try { command1 = new BadRequestCommand(circuitBreaker, ExecutionIsolationStrategy.THREAD); command1.execute(); fail("we expect to receive a " + HystrixBadRequestException.class.getSimpleName()); } catch (HystrixBadRequestException e) { e.printStackTrace(); } assertCommandExecutionEvents(command1, HystrixEventType.BAD_REQUEST); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testBadRequestExceptionViaExecuteInSemaphore() { TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); BadRequestCommand command1 = new BadRequestCommand(circuitBreaker, ExecutionIsolationStrategy.SEMAPHORE); try { command1.execute(); fail("we expect to receive a " + HystrixBadRequestException.class.getSimpleName()); } catch (HystrixBadRequestException e) { e.printStackTrace(); } assertCommandExecutionEvents(command1, HystrixEventType.BAD_REQUEST); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testCheckedExceptionViaExecute() { TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); CommandWithCheckedException command = new CommandWithCheckedException(circuitBreaker); try { command.execute(); fail("we expect to receive a " + Exception.class.getSimpleName()); } catch (Exception e) { assertEquals("simulated checked exception message", e.getCause().getMessage()); } assertEquals("simulated checked exception message", command.getFailedExecutionException().getMessage()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_MISSING); assertNotNull(command.getExecutionException()); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testSemaphoreExecutionWithTimeout() { TestHystrixCommand<Boolean> cmd = new InterruptibleCommand(new TestCircuitBreaker(), false); System.out.println("Starting command"); long timeMillis = System.currentTimeMillis(); try { cmd.execute(); fail("Should throw"); } catch (Throwable t) { assertNotNull(cmd.getExecutionException()); System.out.println("Unsuccessful Execution took : " + (System.currentTimeMillis() - timeMillis)); assertCommandExecutionEvents(cmd, HystrixEventType.TIMEOUT, HystrixEventType.FALLBACK_MISSING); assertEquals(0, cmd.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); } }
@Test public void testRecoverableErrorWithNoFallbackThrowsError() { TestHystrixCommand<Integer> command = getRecoverableErrorCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED); try { command.execute(); fail("we expect to receive a " + Error.class.getSimpleName()); } catch (Exception e) { assertEquals("Execution ERROR for TestHystrixCommand", e.getCause().getCause().getMessage()); } assertEquals("Execution ERROR for TestHystrixCommand", command.getFailedExecutionException().getCause().getMessage()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_MISSING); assertNotNull(command.getExecutionException()); assertEquals(0, command.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testRecoverableErrorMaskedByFallbackButLogged() { TestHystrixCommand<Integer> command = getRecoverableErrorCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.FallbackResult.SUCCESS); assertEquals(FlexibleTestHystrixCommand.FALLBACK_VALUE, command.execute()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS); assertNotNull(command.getExecutionException()); assertEquals(0, command.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testUnrecoverableErrorThrownWithNoFallback() { TestHystrixCommand<Integer> command = getUnrecoverableErrorCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.FallbackResult.UNIMPLEMENTED); try { command.execute(); fail("we expect to receive a " + Error.class.getSimpleName()); } catch (Exception e) { assertEquals("Unrecoverable Error for TestHystrixCommand", e.getCause().getCause().getMessage()); } assertEquals("Unrecoverable Error for TestHystrixCommand", command.getFailedExecutionException().getCause().getMessage()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE); assertNotNull(command.getExecutionException()); assertEquals(0, command.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testUnrecoverableErrorThrownWithFallback() { TestHystrixCommand<Integer> command = getUnrecoverableErrorCommand(ExecutionIsolationStrategy.THREAD, AbstractTestHystrixCommand.FallbackResult.SUCCESS); try { command.execute(); fail("we expect to receive a " + Error.class.getSimpleName()); } catch (Exception e) { assertEquals("Unrecoverable Error for TestHystrixCommand", e.getCause().getCause().getMessage()); } assertEquals("Unrecoverable Error for TestHystrixCommand", command.getFailedExecutionException().getCause().getMessage()); assertTrue(command.getExecutionTimeInMilliseconds() > -1); assertTrue(command.isFailedExecution()); assertCommandExecutionEvents(command, HystrixEventType.FAILURE); assertNotNull(command.getExecutionException()); assertEquals(0, command.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testExecutionFailureWithFallbackImplementedButDisabled() { TestHystrixCommand<Boolean> commandEnabled = new KnownFailureTestCommandWithFallback(new TestCircuitBreaker(), true); try { assertEquals(false, commandEnabled.execute()); } catch (Exception e) { e.printStackTrace(); fail("We should have received a response from the fallback."); } TestHystrixCommand<Boolean> commandDisabled = new KnownFailureTestCommandWithFallback(new TestCircuitBreaker(), false); try { assertEquals(false, commandDisabled.execute()); fail("expect exception thrown"); } catch (Exception e) { } assertEquals("we failed with a simulated issue", commandDisabled.getFailedExecutionException().getMessage()); assertTrue(commandDisabled.isFailedExecution()); assertCommandExecutionEvents(commandEnabled, HystrixEventType.FAILURE, HystrixEventType.FALLBACK_SUCCESS); assertCommandExecutionEvents(commandDisabled, HystrixEventType.FAILURE); assertNotNull(commandDisabled.getExecutionException()); assertEquals(0, commandDisabled.getBuilder().metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(2); }
@Test public void testExecutionTimeoutValue() { HystrixCommand.Setter properties = HystrixCommand.Setter .withGroupKey(HystrixCommandGroupKey.Factory.asKey("TestKey")) .andCommandPropertiesDefaults(HystrixCommandProperties.Setter() .withExecutionTimeoutInMilliseconds(50)); HystrixCommand<String> command = new HystrixCommand<String>(properties) { @Override protected String run() throws Exception { Thread.sleep(3000); return "hello"; } @Override protected String getFallback() { if (isResponseTimedOut()) { return "timed-out"; } else { return "abc"; } } }; String value = command.execute(); assertTrue(command.isResponseTimedOut()); assertEquals("expected fallback value", "timed-out", value); }
@Test public void testExceptionConvertedToBadRequestExceptionInExecutionHookBypassesCircuitBreaker() { TestCircuitBreaker circuitBreaker = new TestCircuitBreaker(); ExceptionToBadRequestByExecutionHookCommand command = new ExceptionToBadRequestByExecutionHookCommand(circuitBreaker, ExecutionIsolationStrategy.THREAD); try { command.execute(); fail("we expect to receive a " + HystrixBadRequestException.class.getSimpleName()); } catch (HystrixBadRequestException e) { e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); fail("We expect a " + HystrixBadRequestException.class.getSimpleName() + " but got a " + e.getClass().getSimpleName()); } assertCommandExecutionEvents(command, HystrixEventType.BAD_REQUEST); assertEquals(0, circuitBreaker.metrics.getCurrentConcurrentExecutionCount()); assertSaneHystrixRequestLog(1); }
@Test public void testChainedCommand() { class SubCommand extends TestHystrixCommand<Integer> { public SubCommand(TestCircuitBreaker circuitBreaker) { super(testPropsBuilder().setCircuitBreaker(circuitBreaker).setMetrics(circuitBreaker.metrics)); } @Override protected Integer run() throws Exception { return 2; } } class PrimaryCommand extends TestHystrixCommand<Integer> { public PrimaryCommand(TestCircuitBreaker circuitBreaker) { super(testPropsBuilder().setCircuitBreaker(circuitBreaker).setMetrics(circuitBreaker.metrics)); } @Override protected Integer run() throws Exception { throw new RuntimeException("primary failure"); } @Override protected Integer getFallback() { SubCommand subCmd = new SubCommand(new TestCircuitBreaker()); return subCmd.execute(); } } assertTrue(2 == new PrimaryCommand(new TestCircuitBreaker()).execute()); }
@Test public void testSlowFallback() { class PrimaryCommand extends TestHystrixCommand<Integer> { public PrimaryCommand(TestCircuitBreaker circuitBreaker) { super(testPropsBuilder().setCircuitBreaker(circuitBreaker).setMetrics(circuitBreaker.metrics)); } @Override protected Integer run() throws Exception { throw new RuntimeException("primary failure"); } @Override protected Integer getFallback() { try { Thread.sleep(1500); return 1; } catch (InterruptedException ie) { System.out.println("Caught Interrupted Exception"); ie.printStackTrace(); } return -1; } } assertTrue(1 == new PrimaryCommand(new TestCircuitBreaker()).execute()); }
@Test public void testOnRunStartHookThrowsSemaphoreIsolated() { final AtomicBoolean exceptionEncountered = new AtomicBoolean(false); final AtomicBoolean onThreadStartInvoked = new AtomicBoolean(false); final AtomicBoolean onThreadCompleteInvoked = new AtomicBoolean(false); final AtomicBoolean executionAttempted = new AtomicBoolean(false); class FailureInjectionHook extends HystrixCommandExecutionHook { @Override public <T> void onExecutionStart(HystrixInvokable<T> commandInstance) { throw new HystrixRuntimeException(HystrixRuntimeException.FailureType.COMMAND_EXCEPTION, commandInstance.getClass(), "Injected Failure", null, null); } @Override public <T> void onThreadStart(HystrixInvokable<T> commandInstance) { onThreadStartInvoked.set(true); super.onThreadStart(commandInstance); } @Override public <T> void onThreadComplete(HystrixInvokable<T> commandInstance) { onThreadCompleteInvoked.set(true); super.onThreadComplete(commandInstance); } } final FailureInjectionHook failureInjectionHook = new FailureInjectionHook(); class FailureInjectedCommand extends TestHystrixCommand<Integer> { public FailureInjectedCommand(ExecutionIsolationStrategy isolationStrategy) { super(testPropsBuilder().setCommandPropertiesDefaults(HystrixCommandPropertiesTest.getUnitTestPropertiesSetter().withExecutionIsolationStrategy(isolationStrategy)), failureInjectionHook); } @Override protected Integer run() throws Exception { executionAttempted.set(true); return 3; } } TestHystrixCommand<Integer> semaphoreCmd = new FailureInjectedCommand(ExecutionIsolationStrategy.SEMAPHORE); try { int result = semaphoreCmd.execute(); System.out.println("RESULT : " + result); } catch (Throwable ex) { ex.printStackTrace(); exceptionEncountered.set(true); } assertTrue(exceptionEncountered.get()); assertFalse(onThreadStartInvoked.get()); assertFalse(onThreadCompleteInvoked.get()); assertFalse(executionAttempted.get()); assertEquals(0, semaphoreCmd.metrics.getCurrentConcurrentExecutionCount()); }
@Test public void testOnRunStartHookThrowsThreadIsolated() { final AtomicBoolean exceptionEncountered = new AtomicBoolean(false); final AtomicBoolean onThreadStartInvoked = new AtomicBoolean(false); final AtomicBoolean onThreadCompleteInvoked = new AtomicBoolean(false); final AtomicBoolean executionAttempted = new AtomicBoolean(false); class FailureInjectionHook extends HystrixCommandExecutionHook { @Override public <T> void onExecutionStart(HystrixInvokable<T> commandInstance) { throw new HystrixRuntimeException(HystrixRuntimeException.FailureType.COMMAND_EXCEPTION, commandInstance.getClass(), "Injected Failure", null, null); } @Override public <T> void onThreadStart(HystrixInvokable<T> commandInstance) { onThreadStartInvoked.set(true); super.onThreadStart(commandInstance); } @Override public <T> void onThreadComplete(HystrixInvokable<T> commandInstance) { onThreadCompleteInvoked.set(true); super.onThreadComplete(commandInstance); } } final FailureInjectionHook failureInjectionHook = new FailureInjectionHook(); class FailureInjectedCommand extends TestHystrixCommand<Integer> { public FailureInjectedCommand(ExecutionIsolationStrategy isolationStrategy) { super(testPropsBuilder(new TestCircuitBreaker()).setCommandPropertiesDefaults(HystrixCommandPropertiesTest.getUnitTestPropertiesSetter().withExecutionIsolationStrategy(isolationStrategy)), failureInjectionHook); } @Override protected Integer run() throws Exception { executionAttempted.set(true); return 3; } } TestHystrixCommand<Integer> threadCmd = new FailureInjectedCommand(ExecutionIsolationStrategy.THREAD); try { int result = threadCmd.execute(); System.out.println("RESULT : " + result); } catch (Throwable ex) { ex.printStackTrace(); exceptionEncountered.set(true); } assertTrue(exceptionEncountered.get()); assertTrue(onThreadStartInvoked.get()); assertTrue(onThreadCompleteInvoked.get()); assertFalse(executionAttempted.get()); assertEquals(0, threadCmd.metrics.getCurrentConcurrentExecutionCount()); }