使用 xUnit 和 FakeItEasy 对 Azure functions v3 进行单元测试

Unit testing Azure functions v3 with xUnit and FakeItEasy

我正在尝试对 Azure v3 HTTP 触发器实施一些 unit/integration 测试,并且正在 运行 处理过程中的一些问题。

我之前为使用如下语法的 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,然后断言 return。

我尝试用 Azure 函数做的是基于 OkObjectResult 评估触发器,但在函数内部我有一些方法调用,然后是依赖于方法调用结果的逻辑。 (returning 一个列表,使用 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);

哦还有界面里面的method/type是这样的:

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

错误发生在 SM.Run(x,y) 内部。经过一些调试后,我可以看到 A.CallTo 在测试函数中 return 得到了正确的结果,但是当 Azure 函数被 运行 时,该值不会被保留,这是代码破坏问题。

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

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

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

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

如果 Transaction 结果没有基于值的相等语义,您可能不得不使用其他参数约束机制之一,例如 custom matcher that examines the transaction's properties or maybe even ignore the actual value 使用 A<Transaction>.Ignored .