我正在尝试通过以下方式设置HystrixCommand的行为:
public abstract class AbstractCircuitBreakerCommand<E> extends HystrixCommand<E> {
protected AbstractCircuitBreakerCommand(final String groupKey, final String commandKey) {
this(groupKey, commandKey, TimeUnit.SECONDS, 10, TimeUnit.SECONDS, 3, TimeUnit.SECONDS, 10, 1);
}
protected AbstractCircuitBreakerCommand(
final String groupKey, final String commandKey,
final TimeUnit metricsWindowTimeUnit, final int metricsWindowTime,
final TimeUnit timeoutTimeUnit, final int timeoutTime,
final TimeUnit windowTimeUnit, final int windowTime,
final int threshold) {
super(Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(groupKey))
.andCommandKey(HystrixCommandKey.Factory.asKey(commandKey))
.andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
.withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
.withMetricsRollingStatisticalWindowInMilliseconds((int) metricsWindowTimeUnit.toMillis(metricsWindowTime))
.withExecutionTimeoutEnabled(true)
.withExecutionTimeoutInMilliseconds((int) timeoutTimeUnit.toMillis(timeoutTime))
.withCircuitBreakerEnabled(true)
.withCircuitBreakerRequestVolumeThreshold(threshold)
.withCircuitBreakerErrorThresholdPercentage(0)
.withCircuitBreakerSleepWindowInMilliseconds((int) windowTimeUnit.toMillis(windowTime))
.withFallbackEnabled(true)));
}
}
在接下来的10秒钟(sleepwindowinmilis)中仅发生一个异常(或超时)之后,我期望将输入的命令短路。
要测试它,我要进行下一个单元测试。
public class AbstractCircuitBreakerCommandTest {
private final static int ERROR_VALUE = Integer.MIN_VALUE;
private final static String GROUP_KEY = "GROUP_KEY";
private final static String COMMAND_KEY = "COMMAND_KEY";
@Test
public void testSimpleExecution() {
final int expectedValue = 1;
final SimpleCircuitBreakerCommandToTest circuitBreakerCommand =
new SimpleCircuitBreakerCommandToTest(GROUP_KEY, COMMAND_KEY, value -> expectedValue);
Assert.assertEquals(expectedValue, (int) circuitBreakerCommand.execute());
Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
Assert.assertTrue(circuitBreakerCommand.isSuccessfulExecution());
}
@Test
public void testSimpleUnsuccessfulExecutionBecauseException() {
final SimpleCircuitBreakerCommandToTest circuitBreakerCommand =
new SimpleCircuitBreakerCommandToTest(GROUP_KEY, COMMAND_KEY, value -> {
throw new Exception("Test");
});
Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());
Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
Assert.assertTrue(circuitBreakerCommand.isFailedExecution());
Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
}
@Test
public void testSimpleUnsuccessfulExecutionBecauseTimeout() {
final SimpleCircuitBreakerCommandToTest circuitBreakerCommand =
new SimpleCircuitBreakerCommandToTest(GROUP_KEY, COMMAND_KEY, value -> {
SleepHelper.sleep(TimeUnit.SECONDS, 4); // The default value is -> 3 seconds.
return 1;
});
Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());
Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
Assert.assertTrue(circuitBreakerCommand.isFailedExecution());
Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
}
private static abstract class AbstractCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommand<Integer> {
private final Integer value;
private final TestAction testAction;
protected AbstractCircuitBreakerCommandToTest(
final String groupKey, final String commandKey,
final TestAction testAction) {
this(groupKey, commandKey, 1, testAction);
}
protected AbstractCircuitBreakerCommandToTest(
final String groupKey, final String commandKey,
final Integer value, final TestAction testAction) {
super(groupKey, commandKey);
this.value = value;
this.testAction = testAction;
}
@Override
protected Integer run() throws Exception {
return this.testAction.run(this.value);
}
@Override
protected Integer getFallback() {
return ERROR_VALUE;
}
@FunctionalInterface
interface TestAction {
Integer run(final Integer integer) throws Exception;
}
}
private static class SimpleCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommandToTest {
protected SimpleCircuitBreakerCommandToTest(
final String groupKey, final String commandKey,
final TestAction testAction) {
super(groupKey, commandKey, testAction);
}
}
}
但是isCircuitBreakerOpen()方法在testSimpleUnsuccessfulExecutionBecauseException和testSimpleUnsuccessfulExecutionBecauseTimeout测试中返回false。
有人可以以正确的方式引导我吗?谢谢。
答案 0 :(得分:0)
这些测试中有一些错误,这是固定版本。
public class AbstractCircuitBreakerCommandTest {
private final static int WAIT_WORK_DONE_IN_MS = 800;
private final static int ERROR_VALUE = Integer.MIN_VALUE;
private final static String GROUP_KEY = "GROUP_KEY";
private final static String COMMAND_KEY = "COMMAND_KEY";
@Test
public void testSimpleExecution() {
final int expectedValue = 1;
final HystrixCommand circuitBreakerCommand =
new SimpleCircuitBreakerCommandToTest(GROUP_KEY + "_0", COMMAND_KEY + "_0", value -> value);
Assert.assertEquals(expectedValue, (int) circuitBreakerCommand.execute());
Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
Assert.assertTrue(circuitBreakerCommand.isSuccessfulExecution());
}
@Test
public void testSimpleUnsuccessfulExecutionBecauseException() {
final HystrixCommand circuitBreakerCommand =
new SimpleCircuitBreakerCommandToTest(GROUP_KEY + "_1", COMMAND_KEY + "_1", value -> {
throw new Exception("Test");
});
Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());
SleepHelper.sleep(TimeUnit.MILLISECONDS, WAIT_WORK_DONE_IN_MS);
Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
Assert.assertTrue(circuitBreakerCommand.isFailedExecution());
Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
}
@Test
public void testSimpleUnsuccessfulExecutionBecauseTimeout() {
final HystrixCommand circuitBreakerCommand =
new SimpleCircuitBreakerCommandToTest(GROUP_KEY + "_2", COMMAND_KEY + "_2", value -> {
SleepHelper.sleep(TimeUnit.SECONDS, 4); // The default value is -> 3 seconds.
return value;
});
Assert.assertEquals(ERROR_VALUE, (int) circuitBreakerCommand.execute());
SleepHelper.sleep(TimeUnit.MILLISECONDS, WAIT_WORK_DONE_IN_MS);
Assert.assertTrue(circuitBreakerCommand.isExecutionComplete());
Assert.assertTrue(circuitBreakerCommand.isResponseTimedOut());
Assert.assertTrue(circuitBreakerCommand.isCircuitBreakerOpen());
}
private static abstract class AbstractCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommand<Integer> {
private final Integer value;
private final TestAction testAction;
protected AbstractCircuitBreakerCommandToTest(
final String groupKey, final String commandKey,
final TestAction testAction) {
this(groupKey, commandKey, 1, testAction);
}
protected AbstractCircuitBreakerCommandToTest(
final String groupKey, final String commandKey,
final Integer value, final TestAction testAction) {
super(groupKey, commandKey);
this.value = value;
this.testAction = testAction;
}
@Override
protected Integer run() throws Exception {
return this.testAction.run(this.value);
}
@Override
protected Integer getFallback() {
return ERROR_VALUE;
}
@FunctionalInterface
interface TestAction {
Integer run(final Integer integer) throws Exception;
}
}
private static class SimpleCircuitBreakerCommandToTest extends AbstractCircuitBreakerCommandToTest {
protected SimpleCircuitBreakerCommandToTest(
final String groupKey, final String commandKey,
final TestAction testAction) {
super(groupKey, commandKey, testAction);
}
}
}