【问题标题】:Unit testing Azure functions v3 with xUnit and FakeItEasy使用 xUnit 和 FakeItEasy 对 Azure 函数 v3 进行单元测试
【发布时间】:2021-05-26 05:08:45
【问题描述】:

我正在尝试对 Azure v3 HTTP 触发器实施一些单元/集成测试,但在处理过程中遇到了一些问题。

我之前为使用如下语法的 API 控制器编写了一些测试:

TransactionResponse fakeResponse = new TransactionResponse { APIResponse = "Okay" };

var fakeSbus = A.Fake<IServiceBusPlatform>();
var fakeTransaction = A.Fake<ITransaction>();
            
A.CallTo(() => fakeTransaction.CreateTransaction(tran)).Returns(Task.FromResult(fakeResponse.APIResponse));
var controller = new SubmitController(fakeSbus, fakeTransaction);

var result = await controller._transaction.CreateTransaction(tran);
Assert.Equal(fakeResponse.APIResponse, result.ToString());

这很好用,因为它只是测试一个 dbcontext 然后断言返回。

我尝试对 Azure 函数执行的操作是基于 OkObjectResult 评估触发器,但在函数内部我有一些方法调用,然后是依赖于方法调用结果的逻辑。 (返回一个列表,使用 ListMember[0] 的属性来声明一个 var)。像这样:

var BatchResults = await _dbService.RetrieveBatch(session);
var CompanyID = BatchResults[0].CompanyID;

更新:为了更清楚一点,这里是整个测试功能:

var fakeBatch = new List<RetrievedBatch>();
fakeBatch.Add(new RetrievedBatch
{
  CompanyID = new Guid(),
});


var testResponse = new OkObjectResult("OKAY");
var request = A.Fake<HttpRequest>();
request.Method = "POST";
            
byte[] byteArray = Encoding.UTF8.GetBytes(JsonConvert.SerializeObject(fakeTransaction));
MemoryStream stream = new MemoryStream(byteArray);
request.Body = stream;

var logger = A.Fake<ILogger>();

var fakeService = A.Fake<IDbService>();

A.CallTo(() => fakeService.RetrieveBatch(fakeTransaction)).Returns(fakeBatch);

var test = fakeService.RetrieveBatch(fakeTransaction);

var SM = new SessionManager(fakeService);
var response = await SM.Run(request, logger);

哦,接口里面的方法/类型是这样的:

Task<List<RetrievedBatch>> RetrieveBatch(Transaction session);

错误发生在 SM.Run(x,y) 内部。经过一些调试,我可以看到 A.CallTo 在测试函数内部返回了正确的结果,但是当 Azure 函数运行时,该值没有被继承,这是代码破坏问题。

任何帮助都将不胜感激,因为我花了太多时间试图解决这个问题,并且所有示例都是基本的,不幸的是在这种情况下没有太大帮助。

【问题讨论】:

  • 显示正在测试的实际功能和现在的完整测试。正如您目前所拥有的那样,显示的 sn-ps 过于脱节,无法正确评估问题。您很可能没有正确配置参数匹配器,这导致模拟默认返回 null。
  • 我已经用我的函数中的代码进行单元测试更新了我的问题:)

标签: c# azure unit-testing fakeiteasy


【解决方案1】:

我认为真正的问题是fakeTransactionSM.Run 调用中与测试中的对象不同。究竟是什么课?我们没有上面fakeTransaction 的定义,但我看到您将它的序列化表示发送到请求中,而不是原始对象。

所以SM.Run 最终使用重构的session 对象调用fakeService.RetrieveBatch(Transaction session)Transaction 类的相等语义是什么?配置的 Fake 的RetrieveBatch 方法将如argument constraints 中所述,使用object.Equals 将其输入与fakeTransaction 进行比较,如果不匹配,则不会触发您配置的行为。

如果您不确定Transaction 的相等语义,请考虑在测试中直接从字节数组重构事务,并在两个对象上运行object.Equals。这将显示它们是否相等。

如果Transaction 没有基于值的相等语义,您可能必须使用其他参数约束机制之一,例如检查事务属性的custom matcher,甚至可能使用ignore the actual value A&lt;Transaction&gt;.Ignored.

【讨论】:

  • 你说得对,我添加了 A.Ignored 语句作为函数参数,然后在调试中我可以发现我期望看到的内容。我不想浪费太多时间创建一个自定义匹配器,因为在这种情况下我知道我只会传递一个类似属性的对象,尽管将来可能需要研究它。感谢您的快速回复和建议,非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-02
  • 2021-10-20
  • 2010-11-16
相关资源
最近更新 更多