Java Guava Retry:无法测试InterruptedException上的重试逻辑 目标:
为了测试当某个函数抛出异常时,会重试X次 限制条件: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
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