Java Guava Retry:无法测试InterruptedException上的重试逻辑 目标:

Java Guava Retry:无法测试InterruptedException上的重试逻辑 目标:,java,easymock,Java,Easymock,为了测试当某个函数抛出异常时,会重试X次 限制条件: 需要使用EasyMock(在单元测试中具有一致的模拟框架) 代码段: 商业代码 import com.github.rholder.retry.Retryer; 导入com.github.rholder.retry.RetryerBuilder; 类重试{ 公共检索器getRetryer(){ return RetryerBuilder.newBuilder() .RetryFeException() .withWaitStrategy(wa

为了测试当某个函数抛出异常时,会重试X次

限制条件:
  • 需要使用EasyMock(在单元测试中具有一致的模拟框架)
  • 代码段: 商业代码
    import com.github.rholder.retry.Retryer;
    导入com.github.rholder.retry.RetryerBuilder;
    类重试{
    公共检索器getRetryer(){
    return RetryerBuilder.newBuilder()
    .RetryFeException()
    .withWaitStrategy(waitStrategy())//尝试3次
    .withStopStrategy(stopStrategy())
    .withAttemptTimeLimiter(attemptTimeLimiter())
    .build();
    }
    }
    类用户类
    {
    私有最终externalTeamLibrary;//和接受它的构造函数
    PublicPublishSync(某些输入,重试retryParameters)
    {
    可调用的可发布的可调用的=
    ()->publishAsync(一些输入)//返回未来对象
    .get(retryParameters.CallTimeOutims(),TimeUnit.millizes);
    返回retryParameters.getRetryer().call(publishCallable);
    }
    public Future publishAsync(一些输入)
    {
    return externalTeamLibrary.send(obj1,obj2);//返回未来对象
    }
    }
    
    测试代码
    @测试
    公共无效测试函数()
    {
    //实物
    Retry realRetryInstance=//获取一个实例的方法
    //嘲弄
    ExternalTeamLibraryClass externalTeamLibraryMock=createMock(ExternalTeamLibraryClass.class);
    //期望值和回报值
    expect(externalTeamLibraryMock.send(anyObject(),anyObject()))
    .anthrow(新的中断异常(“test1”))
    .次(3);
    EasyMock.replay(externalTeamLibraryMock);
    UserClass user=新的UserClass(externalTeamLibraryMock,其他东西);
    publishSync(someRealInputs、realRetryInstance);
    //验证使用的所有模拟
    EasyMock.verify(externalTeamLibraryMock);
    }
    
    我想发生的事 在显式调用publishSync并使externalTeamLibrary.send()抛出异常时,我希望真正的重试对象“重试”publishAsync()。重试限制为3,因此我希望对externalTeamLibrary.send()进行三次调用

    但我得到以下错误

    堆栈跟踪
    [junit]Testcase:testFunction:导致错误
    [junit]尝试1次后重试失败。
    [junit]com.github.rholder.retry.RetryException:尝试1次后重试失败。
    [junit]位于com.github.rholder.retry.Retryer.call(Retryer.java:181)
    [junit]位于UserClass.publish
    [junit]位于TestClass.testFunction
    [junit]由以下原因引起:org.apache.kafka.common.errors.InterruptException:test1
    [junit]位于org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:46)
    [junit]位于org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94)
    [junit]位于org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:97)
    [junit]位于externalTeamLibrary$$EnhancerByGlib$$f53a1a7e.send()上
    [junit]位于UserClass.publishAsync(第175行)
    [junit]位于UserClass.lambda$publish$1(lineZ:209)
    [junit]位于com.github.rholder.retry.AttemptTimeLimiters$NoAttemptTimeLimit.call(AttemptTimeLimiters.java:78)
    [junit]位于com.github.rholder.retry.Retryer.call(Retryer.java:160)
    [junit]由以下原因引起:java.lang.InterruptedException
    [junit]位于org.apache.kafka.common.errors.InterruptException.(InterruptException.java:35)
    [junit]位于TestClass.testFunction
    

    在抛出InterruptException的行上发生错误


    更新1 我刚顿悟过来。 如果我的外部库模拟抛出的不是
    org.apache.kafka.common.errors.InterruptException
    ,则重试失败,并显示正确的消息重试失败,在尝试3次后成功完成。

    但是,当我的模拟抛出中断异常时,在第一次尝试之后重试失败。两种情况下的故障点不同。 ,第174行是“快乐案例”,其中使用了停止策略。第181行表示否定情况,其中InterruptException导致InterruptedException

    显示kafka的InterruptException只是InterruptedException的包装器。
    因此,真正的问题是如何成功地重试。如果线程在尝试执行任务时被中断,我觉得应该重试,因为我们不确定它是否无法恢复。

    重试者正在抛出异常。这是由真实代码引起的。所以我想说,回收机坏了。你为什么不这么想?我发现这个错误消息来自我不确定是什么导致了InterruptedException。Retryer是标准guava retry库的一部分。我想它不会坏的。无论是代码还是junit框架都会导致线程中断锁从根本上说是容易出错的-如果您在使用mock时遇到奇怪的不变中断事件,那么您应该做的第一件事就是停止mock<代码>InterruptedException特别关注线程范围内的语义问题,可能无法很好地处理EasyMock这样具有侵入性的东西。您可能希望联系
    ExternalTeamLibraryClass
    的所有者,看看他们是否可以为编写使用其库的测试提供更好的方法。我怀疑他们会说“不要嘲笑我们的图书馆!”github.com/rholder/guava-retrying似乎不是guava的官方部分。该名称可能有误导性。Retryer正在引发异常。这是由真实代码引起的。所以我想说,回收机坏了。你为什么不这么想?我发现这个错误消息来自我不确定是什么导致了中断
    [junit] Testcase: testFunction: Caused an ERROR
    [junit] Retrying failed to complete successfully after 1 attempts.
    [junit] com.github.rholder.retry.RetryException: Retrying failed to complete successfully after 1 attempts.
    [junit]     at com.github.rholder.retry.Retryer.call(Retryer.java:181)
    [junit]     at UserClass.publish
    [junit]     at TestClass.testFunction
    [junit] Caused by: org.apache.kafka.common.errors.InterruptException: test1
    [junit]     at org.easymock.internal.MockInvocationHandler.invoke(MockInvocationHandler.java:46)
    [junit]     at org.easymock.internal.ObjectMethodsFilter.invoke(ObjectMethodsFilter.java:94)
    [junit]     at org.easymock.internal.ClassProxyFactory$MockMethodInterceptor.intercept(ClassProxyFactory.java:97)
    [junit]     at externalTeamLibrary$$EnhancerByCGLIB$$f53a1a7e.send(<generated>)
    [junit]     at UserClass.publishAsync(line:175)
    [junit]     at UserClass.lambda$publish$1(lineZ:209)
    [junit]     at com.github.rholder.retry.AttemptTimeLimiters$NoAttemptTimeLimit.call(AttemptTimeLimiters.java:78)
    [junit]     at com.github.rholder.retry.Retryer.call(Retryer.java:160)
    [junit] Caused by: java.lang.InterruptedException
    [junit]     at org.apache.kafka.common.errors.InterruptException.<init>(InterruptException.java:35)
    [junit]     at TestClass.testFunction