Polly 重试单元测试

2023-12-19

我正在使用 polly 来处理重试(参见下面的代码)。如何对 polly 重试进行单元测试?使用 xunit 和最小起订量

services.AddHttpClient("GitHub", client =>
{
    client.BaseAddress = new Uri("https://api.github.com/");
    client.DefaultRequestHeaders.Add("Accept", "application/vnd.github.v3+json");
})
.AddTransientHttpErrorPolicy(builder => builder.WaitAndRetryAsync(new[]
{
    TimeSpan.FromSeconds(1),
    TimeSpan.FromSeconds(5),
    TimeSpan.FromSeconds(10)
}));

正如我推荐的评论中所建议的Simmy https://github.com/Polly-Contrib/Simmy.

它允许您注入异常、返回BadRequests等等,以触发 Polly 的故障和弹性策略,例如WaitAndRetry.

这些是来自文档 https://github.com/Polly-Contrib/Simmy/blob/master/README.md.

注入(Socket)异常

var chaosPolicy = MonkeyPolicy.InjectException(Action<InjectOutcomeOptions<Exception>>);

例如:它导致策略抛出SocketException如果启用,概率为 5%

var fault = new SocketException(errorCode: 10013);
var chaosPolicy = MonkeyPolicy.InjectException(with =>
    with.Fault(fault)
        .InjectionRate(0.05)
        .Enabled()
    );

注入(BadRequest)结果

var chaosPolicy = MonkeyPolicy.InjectResult(Action<InjectOutcomeOptions<TResult>>);

例如:如果启用,它会导致策略返回错误请求 HttpResponseMessage,概率为 5%

var result = new HttpResponseMessage(HttpStatusCode.BadRequest);
var chaosPolicy = MonkeyPolicy.InjectResult<HttpResponseMessage>(with =>
    with.Result(result)
        .InjectionRate(0.05)
        .Enabled()
);

只需设置InjectionRate to 1以保证您的单元测试出现错误。


如果您想使用InjectionRate小于 1 您可以通过以下方式使用 xunit 和 moq 链接SetupSequence and Moq.Language.ISetupSequentialResult。这是我必须做的区块链挑战的一个示例,我连续执行 4 个调用,因此如果 InjectionRate 为 0.25,4 个调用之一将触发 Polly 策略:

[Fact]
public async Task Should_Return_GetEthereumTransactionsAsync()
{
    // Arrange
    IConfiguration settings = new ConfigurationBuilder().AddJsonFile("appsettings.json").Build();
    IOptions<Settings> optionSettings = Options.Create(new Settings
    {
        CompanyKeyAPI = settings.GetSection("CompanyKeyAPI").Value,
        ProjectId = settings.GetSection("ProjectId").Value
    });

    var sequenceHttpResponse = new List<Tuple<HttpStatusCode, HttpContent>>
    {
        new Tuple<HttpStatusCode, HttpContent>(HttpStatusCode.OK, ApiCompanyKeyResponses.EthereumBlockWithTransactionHashs()),
        new Tuple<HttpStatusCode, HttpContent>(HttpStatusCode.OK, ApiCompanyKeyResponses.Transaction(1)),
        new Tuple<HttpStatusCode, HttpContent>(HttpStatusCode.OK, ApiCompanyKeyResponses.Transaction(2)),
        new Tuple<HttpStatusCode, HttpContent>(HttpStatusCode.OK, ApiCompanyKeyResponses.Transaction(3))
    };

    IHttpClientFactory httpClientFactory = base.GetChainedCompanyKeyHttpClientFactory(new Uri(Path.Combine(optionSettings.Value.CompanyKeyAPI, optionSettings.Value.ProjectId)), sequenceHttpResponse);
    CompanyKeyService CompanyKeyService = new CompanyKeyService(httpClientFactory);

    // Act
    List<EthereumTransaction> ethereumTransactionsResult = CompanyKeyService.GetEthereumTransactionsAsync(blockNumber, address).Result;

    // Assert
    Assert.IsType<List<EthereumTransaction>>(ethereumTransactionsResult);
    Assert.NotNull(ethereumTransactionsResult);
    Assert.Equal(ethereumTransactionsResult.Count, 3);
    Assert.Equal(ethereumTransactionsResult[0].result.blockHash, blockHash);
}


public IHttpClientFactory GetChainedCompanyKeyHttpClientFactory(Uri uri, List<Tuple<HttpStatusCode, HttpContent>> httpReturns, HttpStatusCode statusCode = HttpStatusCode.OK)
{
    Mock<HttpMessageHandler> httpMsgHandler = new Mock<HttpMessageHandler>();
    var handlerPart = httpMsgHandler.Protected().SetupSequence<Task<HttpResponseMessage>>("SendAsync", new object[2]
    {
        ItExpr.IsAny<HttpRequestMessage>(),
        ItExpr.IsAny<CancellationToken>()
    });

    foreach (var httpResult in httpReturns)
    {
        handlerPart = AddReturnPart(handlerPart, httpResult.Item1, httpResult.Item2);
    }
    httpMsgHandler.Verify();

    HttpClient client = new HttpClient(httpMsgHandler.Object)
    {
        BaseAddress = uri
    };
    Mock<IHttpClientFactory> clientFactory = new Mock<IHttpClientFactory>();
    clientFactory.Setup((IHttpClientFactory cf) => cf.CreateClient(It.IsAny<string>())).Returns(client);
            
    return clientFactory.Object;
}

private Moq.Language.ISetupSequentialResult<Task<HttpResponseMessage>> AddReturnPart(Moq.Language.ISetupSequentialResult<Task<HttpResponseMessage>> handlerPart,
HttpStatusCode statusCode, HttpContent content)
    {
        return handlerPart

        // prepare the expected response of the mocked http call
        .ReturnsAsync(new HttpResponseMessage()
        {
            StatusCode = statusCode, 
            Content = content
        });
    }

....

public class CompanyKeyService : ICompanyKeyService
{
    private readonly IHttpClientFactory _clientFactory;
    private readonly HttpClient _client;
    public CompanyKeyService(IHttpClientFactory clientFactory)
    {
        _clientFactory = clientFactory;
        _client = _clientFactory.CreateClient("GitHub");
    }

    public async Task<List<EthereumTransaction>> GetEthereumTransactionsAsync(string blockNumber, string address)
    {
        //Validation removed...
   
        List<string> transactionHashs = await GetEthereumTransactionHashsByBlockNumberAsync(blockNumber);
        if (transactionHashs == null) throw new Exception("Invalid entry. Please check the Block Number.");
        var tasks = transactionHashs.Select(hash => GetTransactionByHashAsync(hash, address));
        EthereumTransaction[] lists = await Task.WhenAll(tasks);
        return lists.Where(item => item != null).ToList();
    }
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Polly 重试单元测试 的相关文章

  • 尝试了解使用服务打开对话框

    我已经阅读了有关使用 mvvm 模式打开对话框的讨论 我看过几个使用服务的示例 但我不明白所有部分如何组合在一起 我发布这个问题寻求指导 以了解我应该阅读哪些内容 以更好地理解我所缺少的内容 我将在下面发布我所拥有的内容 它确实有效 但从我
  • 在 CPP 类中将 C 函数声明为友元

    我需要在 C 函数中使用类的私有变量 我正在做这样的事情 class Helper private std string name public std getName return name friend extern C void in
  • Environment.CurrentDirectory 与 System.IO.Directory.GetCurrentDirectory

    我正在编写一个 Net WinForms 并不断在调试和发布配置之间切换 并且有一些文件我需要任一配置才能访问 我想做的是将文件放在 BIN 文件夹中的公共目录中 这样它看起来像这样 MyProject Bin CommonFiles My
  • extern 声明和函数定义都在同一文件中

    我只是浏览了一下gcc源文件 在gcc c 我发现了类似的东西 extern int main int char int main int argc char argv 现在我的疑问是extern是告诉编译器特定的函数不在这个文件中 但可以
  • 强制初始化模板类的静态数据成员

    关于模板类的静态数据成员未初始化存在一些问题 不幸的是 这些都没有能够帮助我解决我的具体问题的答案 我有一个模板类 它有一个静态数据成员 必须为特定类型显式实例化 即必须专门化 如果不是这种情况 使用不同的模板函数应该会导致链接器错误 这是
  • 在 C# 中,如何根据在 gridview 行中单击的按钮引用特定产品记录

    我有一个显示产品网格视图的页面 该表内有一列 其中有一个名为 详细信息 的超链接 我想这样做 以便如果用户单击该特定产品的详细信息单元格 将打开一个新页面 提供有关该产品的更多信息 我不确定如何确定哪个Product记录链接的详细信息以及我
  • 即使没有异步,CallContext.LogicalGetData 也会恢复。为什么?

    我注意到CallContext LogicalSetData LogicalGetData不按照我期望的方式工作 内部设置的值async方法得到恢复即使没有异步或任何类型的线程切换 无论如何 这是一个简单的例子 using System u
  • C++中判断unicode字符是全角还是半角

    我正在编写一个终端 控制台 应用程序 该应用程序应该包装任意 unicode 文本 终端通常使用等宽 固定宽度 字体 因此要换行文本 只需计算字符数并观察单词是否适合一行并采取相应的操作 问题是 Unicode 表中的全角字符在终端中占用了
  • 是否使用 C# 数据集? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我对 C 中的数据集概念有点困惑 编码 ASP NET 站点 但这并不重要 在我的阅读中 我了解到它们 本质上 用作我的应用程序和我的
  • 从网页运行 ClickOnce 应用程序,无需用户操作

    我们有一个基于 Java 的 Web 应用程序以及用 C 编写的相同应用程序 如果 java 检查器发现客户端计算机上没有安装 Java 则应该运行该应用程序 这个想法是运行 C 单击一次 http en wikipedia org wik
  • 如果输入被重定向则执行操作

    我想知道如果我的输入被重定向 我应该如何在 C 程序中执行操作 例如 假设我有已编译的程序 prog 并且我将输入 input txt 重定向到它 我这样做 prog lt input txt 我如何在代码中检测到这一点 一般来说 您无法判
  • 模板外部链接?谁能解释一下吗?

    模板名称具有链接 3 5 非成员函数模板可以有内部链接 任何其他模板名称应具有外部链接 从具有内部链接的模板生成的实体与在其他翻译单元中生成的所有实体不同 我知道使用关键字的外部链接 extern C EX extern C templat
  • 在 C# 中为父窗体中的子窗体控件添加事件处理程序

    我有两种形式 一种是带有按钮和文本框的父表单 单击该按钮时 将打开一个对话框 该子窗体又包含一个文本框和一个按钮 现在我想要的是 每当子表单文本框中的文本更改时 父表单文本框中的文本会自动更改 为了获得这个 我所做的是 Form3 f3 n
  • C++ - 多维数组

    处理多维数组时 是否可以为数组分配两种不同的变量类型 例如你有数组int example i j 有可能吗i and j是两种完全不同的变量类型 例如 int 和 string 听起来您正在寻找 std vector
  • 比较:接口方法、虚方法、抽象方法

    它们各自的优点和缺点是什么 接口方法 虚拟方法 抽象方法 什么时候应该选择什么 做出这一决定时应牢记哪些要点 虚拟和抽象几乎是一样的 虚方法在基类中有一个实现 可以选择重写 而抽象方法则没有 并且must在子类中被覆盖 否则它们是相同的 在
  • C++ 对象用 new 创建,用 free() 销毁;这有多糟糕?

    我正在修改一个相对较大的 C 程序 不幸的是 并不总是清楚我之前的人使用的是 C 还是 C 语法 这是在一所大学的电气工程系 我们 EE 总是想用 C 来做所有事情 不幸的是 在这种情况下 人们实际上可以逃脱惩罚 但是 如果有人创建一个对象
  • 将 Lambda 表达式树与 IEnumerable 结合使用

    我一直在尝试了解有关使用 Lamba 表达式树的更多信息 因此我创建了一个简单的示例 这是代码 如果作为 C 程序粘贴到 LINQPad 中 它可以工作 void Main IEnumerable
  • C++:二叉树所有节点值的总和

    我正在准备面试 我被一个二叉树问题困住了 我们如何计算二叉树所有节点中存在的值的总和 优雅的递归解决方案 伪代码 def sum node if node NULL return 0 return node gt value sum nod
  • 如何在 sql azure 上运行 aspnet_regsql? [复制]

    这个问题在这里已经有答案了 可能的重复 将 ASP NET 成员资格数据库迁移到 SQL Azure https stackoverflow com questions 10140774 migrating asp net membersh
  • 无法将字符串文字分配给装箱的 std::string 向量

    这是我的类型系统的简化版本 include

随机推荐

  • 在 Java 中从 json 文件中删除 json 对象

    我有一个在线下载的 json 文件 price 1 empty 0 0 0 0 0 lowValue 0 highValue 0 我想删除其中的所有内容 空的 to 我花了几个小时研究正则表达式的东西 但我似乎不知道如何让它做我想做的事情
  • 在两个数组中查找唯一元素索引的 Pythonic 方法

    我有两个类似于这些的已排序的 numpy 数组 x np array 1 2 8 11 15 y np array 1 8 15 17 20 21 元素在同一个数组中永远不会重复 我想找出一个办法蟒蛇找出包含数组中存在相同元素的位置的索引列
  • Appcelerator Titanium:代码签名错误:未找到代码签名身份

    这让我发疯 我现在花了大约 10 个小时删除和重新生成我的 Appcelerator Titanium iPad 应用程序的 Apple 密钥和配置文件 一年前我已经完成了所有工作和编译 然后我的 Mac 崩溃了 我不得不重新格式化并重新开
  • “jmeter”不被识别为内部或外部命令、可操作程序或批处理文件

    当我在命令行模式下运行 JMeter 脚本时 出现以下错误 但相同的脚本在 GUI 模式下运行得非常好 这里需要一些帮助来解决这个问题 下面是错误 C Users Sundarapandiyan gt jmeter n t D JMETER
  • 将列表中找到的 ID 添加到 pandas 数据框中的新列

    假设我有以下数据框 一列整数和一列包含整数列表 ID Found IDs 0 12345 15443 15533 3433 1 15533 2234 16608 12002 7654 2 6789 43322 876544 36789 还有
  • 如何在 Ruby on Rails 中解析翻译后的日期?

    我已经在 Ruby on Rails 中配置了一个应用程序 并将其翻译为西班牙语 现在我需要解析翻译后的日期 例如 Jueves 2012 年 11 月 22 日 我正在尝试这样做 Date strptime Jueves 22 de No
  • python:来自多个字典的联合键?

    我有 5 个字典 我想要它们的键的并集 alldict dict1 dict2 dict3 dict4 dict5 I tried allkey reduce lambda x y set x keys union y keys alldi
  • 如何在没有 foreach 的情况下使用 PHP 生成器?

    这是一个简单的 JavaScript 生成器 通过 http blog carbon Five com 2013 12 01 hanging up on callbacks generators in ecmascript 6 http b
  • 使用 $in 查询更新 mongodb?

    我有三个数组 coupon ids id counter 和increase ctr 现在 任何索引处的 coupon id 值都出现在 id counter 和increase ctr 中的同一索引处 因此 对于 coupon id 58
  • 拖放 Datagridview Winform C# 的行

    我想将行从同一网格视图中的某个位置拖动到另一个位置 其他行应根据拖放自动调整 谢谢 在应用程序中进行拖放操作时 我更喜欢使用鼠标事件而不是实际的拖放事件 1 未绑定示例 这是一个简单的示例 使用鼠标事件在显示行时拖动行Cell值在一个Lab
  • 扩展 Doctrine Entity 以添加业务逻辑

    我正在尝试实践良好的设计并扩展 Doctrine 实体 我的扩展类 基本上是模型 将具有额外的业务逻辑 对实体基本数据的访问 我正在使用 Doctrine 2 2 1 和 Zend Framework 1 11 4 和 php 5 3 8
  • Google Sheet 脚本显然没有返回数字

    我正在用 Google Script 编写我的第一个自定义函数 一切都在调试中运行良好 我的代码运行 显然 完美 已经写了一个函数 CONVERT RACETIME TO SECONDS 它接受特定格式的字符串 然后返回秒数 然后 该函数应
  • 如何快速了解 SQLite 中的表结构?

    是否有类似 显示 TABLENAME 中的列 之类的命令 我只知道 dump 命令 但在这种情况下这真的很愚蠢 它还会输出所有数据 我需要一些东西来查看表结构 你需要使用一个PRAGMA http www sqlite org pragma
  • Angular 2:在所有组件中使用的函数

    我有一个 Angular 2 webpack 项目 其中目前有一些在多个组件中重复的功能 我想从 主 类或组件 以有效者为准 继承所有这些组件 以便能够从所有需要它们的组件中调用我的函数 举个例子 如果我在 3 个不同的组件中有一个函数 f
  • android studio 下载 windows XP

    我一直在尝试下载Android Studio过去一周左右 但一直没能做到 我还在奔跑windows XP on a Dell d430 如果有帮助的话 提取文件时发生错误 如果您可以提供一个可以下载 android studio 的链接Wi
  • 如何确定我们来自哪个活动?

    老体育你好 到目前为止 我有 3 项活动如下 活动A 活动B 活动C 在活动 A 中 我创建了前往活动 C 的意图 Intent intent new Intent getActivity C class startActivity int
  • 如何更新“更新程序”? (C#)

    我有一个由两个程序组成的程序 Updater 和 WorkMaker 每当 WorkMaker 有更新时 更新程序都会终止它 下载更新 然后再次运行它 但假设我想出了新的更新程序 我该如何更新它 通过WorkMaker 通过第三个程序 谢谢
  • 如何获取行中的所有非空单元格数据 - Google Sheets 脚本编辑器

    我不确定这是否可能 而且说实话 我没有尝试很多事情 因为我不知道从哪里开始 顺便说一句 我正在使用 Google Sheets 中的脚本编辑器 我知道有 SpreadsheetApp getRange 和另一个来获取值或类似的东西 但我想要
  • 在 WPF RichTextBox 中将特定文本设置为粗体

    我正在扩展 WPF Richtextbox 的功能 我希望某些文本在输入时变为粗体 我能够将某些文本变为粗体 但粗体单词后面的文本也会变为粗体 这是我的代码示例 private bool Running false void CustomR
  • Polly 重试单元测试

    我正在使用 polly 来处理重试 参见下面的代码 如何对 polly 重试进行单元测试 使用 xunit 和最小起订量 services AddHttpClient GitHub client gt client BaseAddress