【发布时间】:2022-02-22 23:00:34
【问题描述】:
我正在努力扩展 .NET Core 中的 TestMethod 属性。我将 Polly 库用于重试逻辑以及外部超时策略。
我想要一个可以重试调用ITestMethod 直到它通过的辅助方法。我不介意它会被重试多少次。但我会设置一个必须在其中完成的超时。如果委托在超时内成功执行,那就没问题了。但是如果出现超时异常,我还是要失败的结果值(最后一次迭代的结果)而不是TimeOutRejectedException或者返回类型的默认值。
下面是我扩展的测试方法属性类:
public sealed class GuaranteedPassTestMethodAttribute : TestMethodAttribute
{
/// <inheritdoc/>
public override TestResult[] Execute(ITestMethod testMethod)
{
return ExecuteTestTillSuccess(testMethod);
}
private TestResult[] ExecuteTestTillSuccess(ITestMethod testMethod)
{
var gracefulTestRun =
TestExecutionHelper.ExecuteTestTillPassAsync(
() => TestInvokeDelegate(testMethod));
return gracefulTestRun.Result;
}
private Task<TestResult[]> TestInvokeDelegate(ITestMethod testMethod)
{
TestResult[] result = null;
var thread = new Thread(() => result = Invoke(testMethod));
thread.Start();
thread.Join();
return Task.FromResult(result);
}
}
下面是我使用 Polly 的TestExecutionHelper:
internal static class TestExecutionHelper
{
private static readonly Func<TestResult[], bool> TestFailurePredicate =
results => results != null &&
results.Length == 1 &&
results.First().Outcome != UnitTestOutcome.Passed;
internal static async Task<TestResult[]> ExecuteTestTillPassAsync(
Func<Task<TestResult[]>> testInvokeDelegate,
int delayBetweenExecutionInMs = 3000,
int timeoutInSeconds = 60 * 10)
{
var timeoutPolicy = Policy.TimeoutAsync<TestResult[]>(timeoutInSeconds);
var retryPolicy = Policy.HandleResult<TestResult[]>(TestFailurePredicate)
.WaitAndRetryAsync(int.MaxValue, x => TimeSpan.FromMilliseconds(delayBetweenExecutionInMs));
var testRunPolicy = timeoutPolicy.WrapAsync(retryPolicy);
return await testRunPolicy.ExecuteAsync(testInvokeDelegate);
}
}
使用此设置,我要么获得通过的测试方法执行,要么获得 TimeOutRejectedException 用于失败的测试。即使在重试之后,我也想捕获失败的测试 TestResult。
【问题讨论】:
-
能否请您详细说明此代码
Invoke(testMethod)?我可以testMethod.Invoke确实存在,但它返回一个TestResult。
标签: c# unit-testing .net-core polly