繁体   English   中英

如何对 javanica @HystrixCommand 注释方法进行单元测试?

[英]How can I unit-test javanica @HystrixCommand annotated methods?

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

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

而且我正在尝试对我的回退方法进行单元测试,而不必直接调用它们,即我想调用@HystrixCommand注释方法,并在抛出 500 错误后让它自然流入回退。 这一切都在单元测试之外工作。

在我的单元测试中,我使用 springs 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 命令进行 UNIT 测试。 进行某种 spring 混合测试仍然很有用,我认为在添加注释时直接接受该功能是不正确的。 我创建的测试确保断路器在异常情况下打开。

@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);
    }

}

另一件让我感到困惑的小事是我在没有特定命令键的情况下输入了默认注释,但是当创建命令键时,它们是根据我在上面指定的方法名称创建的。 对于一个完整的示例,我还添加了注释以表明我没有指定 commandKey。

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

希望这可以帮助某人。

Hystrix 是一种您认为具有功能性的工具,就像 Spring 是一种您认为具有功能性的工具一样。 您不需要对 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);

我现在遇到了一个问题:如果包装方法的方法签名发生变化,则没有编译时间或引导程序检查回退方法是否仍然可调用。 因此,如果 int arg 更改为 String,而我忘记更改回退方法的签名,则在应用程序运行并调用包装方法之前我不会知道。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM