我如何单位测试Javanica @HyStrixCommand注释方法



我正在使用javanica并注释我的hystrix命令方法:

@HystrixCommand(groupKey="MY_GROUP", commandKey="MY_COMMAND" fallbackMethod="fallbackMethod")
public Object getSomething(Object request) {
....

我正在尝试对我的后备方法进行单元测试,而不必直接调用它们,即我想调用@HystrixCommand注释方法,并在丢弃500误差后自然流入后备。这一切都在单位测试之外工作。

在我的单元测试中,我使用的是弹簧MockRestServiceServer返回500个错误,此部分正常工作,但是HyStrix在我的单位测试中未正确初始化。在我的测试方法开始时,我有:

HystrixRequestContext context = HystrixRequestContext.initializeContext();
myService.myHystrixCommandAnnotatedMethod();

之后,我试图通过键获取任何HyStrix命令,并检查是否有任何执行命令,但列表始终为空,我正在使用此方法:

public static HystrixInvokableInfo<?> getHystrixCommandByKey(String key) {
    HystrixInvokableInfo<?> hystrixCommand = null;
    System.out.println("Current request is " + HystrixRequestLog.getCurrentRequest());
    Collection<HystrixInvokableInfo<?>> executedCommands = HystrixRequestLog.getCurrentRequest()
            .getAllExecutedCommands();
    for (HystrixInvokableInfo<?> command : executedCommands) {
        System.out.println("executed command is " + command.getCommandGroup().name());
        if (command.getCommandKey().name().equals(key)) {
            hystrixCommand = command;
            break;
        }
    }
    return hystrixCommand;
}

我意识到我在单元测试初始化中缺少某些内容,任何人都可以指出我如何正确地测试我的正确方向?

,尽管您不一定应该单位测试hystrix命令。进行弹簧混合动力测试仍然很有用,我认为添加注释时,点空白接受功能是不正确的。我创建的测试可确保断路器在例外打开。

@RunWith(SpringRunner.class)
@SpringBootTest
public class HystrixProxyServiceTests {
    @MockBean
    private MyRepo myRepo;
    @Autowired
    private MyService myService;
    private static final String ID = “1”;
    @Before
    public void setup() {
        resetHystrix();
        openCircuitBreakerAfterOneFailingRequest();
    }
    @Test
    public void circuitBreakerClosedOnSuccess() throws IOException, InterruptedException {
        when(myRepo.findOneById(USER_ID1))
        .thenReturn(Optional.of(Document.builder().build()));
        myService.findOneById(USER_ID1);
        HystrixCircuitBreaker circuitBreaker = getCircuitBreaker();
        Assert.assertTrue(circuitBreaker.allowRequest());
        verify(myRepo, times(1)).findOneById(
            any(String.class));
    }
    @Test
    public void circuitBreakerOpenOnException() throws IOException, InterruptedException {
        when(myRepo.findOneById(ID))
            .thenThrow(new RuntimeException());
        try {
            myService.findOneById(ID);
        } catch (RuntimeException exception) {
            waitUntilCircuitBreakerOpens();
            HystrixCircuitBreaker circuitBreaker = getCircuitBreaker();
            Assert.assertFalse(circuitBreaker.allowRequest());
        }
        verify(myRepo, times(1)).findOneById(
            any(String.class));
    }
    private void waitUntilCircuitBreakerOpens() throws InterruptedException {
        Thread.sleep(1000);
    }
    private void resetHystrix() {
        Hystrix.reset();
    }
    private void warmUpCircuitBreaker() {
        myService.findOneById(USER_ID1);
    }
    public static HystrixCircuitBreaker getCircuitBreaker() {
        return HystrixCircuitBreaker.Factory.getInstance(getCommandKey());
    }
    private static HystrixCommandKey getCommandKey() {
        return HystrixCommandKey.Factory.asKey("findOneById");
    }
    private void openCircuitBreakerAfterOneFailingRequest() {
        ConfigurationManager.getConfigInstance().
            setProperty("hystrix.command.findOneById.circuitBreaker.requestVolumeThreshold", 1);
    }
}

绊倒我一段时间的另一件事是,我已经输入了没有特定命令键的默认注释,但是当创建命令键时,它们是针对我上面指定的方法名称创建的。对于一个完整的示例,我还添加了注释以显示我没有指定命令关键。

@HystrixCommand
public Optional<Document> findOneById(final String id) {
    return this.myRepo.findOneById(id);
}

希望这对某人有帮助。

hyStrix是您接受的工具,就像春天是您接受的工具一样。您无需单元测试Hystrix调用您的后备方法的能力。

您应该通过在单位测试中直接调用后备来测试后备方法。

也就是说,当您希望Hystrix调用后备方法时,您可能想测试Hystrix实际上是在调用后备方法。这不是单位测试,这将是一个集成测试。

虽然可以使用Junit编写许多集成测试,但似乎Hystrix不想参加Junit测试。

我建议您应该在开发和/或QA测试环境中安装您的应用程序,并通过在运行系统上迫使后备来测试HyStrix后备功能。

可能为时已晚。但是您可以使用该方法在代码运行之前实例化

我这样做了

public void warmUpCircuitBreaker() {
    HystrixCommandKey commandKey= HystrixCommandKey.Factory.asKey("test");
    HystrixCommandProperties.Setter setter = HystrixCommandProperties.defaultSetter();

    HystrixPropertiesCommandDefault hystrixPropertiesCommandDefault = new HystrixPropertiesCommandDefault(commandKey, setter);
    HystrixCommandGroupKey test = HystrixCommandGroupKey.Factory.asKey("Test");
    HystrixCircuitBreaker.Factory.getInstance(commandKey,
            test,
            hystrixPropertiesCommandDefault,
            HystrixCommandMetrics.getInstance(commandKey, test, hystrixPropertiesCommandDefault));
}

在调用SUT之前调用此方法您也可以设置所有必需的属性

和我的测试我正在设置属性以测试不同的方案

 ConfigurationManager.getConfigInstance()
            .setProperty("hystrix.command.test.circuitBreaker.forceClosed",
                    true);

我现在遇到了几次问题:如果包装方法的方法签名更改,则没有编译时间或bootstrap检查后返回方法是否仍然可召唤。因此,如果int arg更改为字符串,而我忘了更改后回版方法的签名,那么直到应用程序运行并调用包装方法,我才知道。

相关内容

  • 没有找到相关文章

最新更新