在 Azure Function 中使用 xUnit 的 Moq 服务总线

Posted

技术标签:

【中文标题】在 Azure Function 中使用 xUnit 的 Moq 服务总线【英文标题】:Moq Service Bus using xUnit in Azure Function 【发布时间】:2021-12-22 01:56:55 【问题描述】:

我有实现 HTTP 触发器和服务总线的 Azure 函数。我已经成功完成了 Http Response 的 xUnits 实现,但不确定如何模拟 Azure 服务总线。我不希望代码实际在队列中创建服务总线消息。

 [FunctionName("MyFunction1")]
    public async Task<IActionResult> Run(
        [HttpTrigger(AuthorizationLevel.Function, "post", Route = "POST")] HttpRequest req
        ,[ServiceBus("providerexemptionreceivednotification", Connection = "ProviderExemptionReceivedNotification")] IAsyncCollector<Message> servicebusMessage
        )
    
         //code
         await servicebusMessage.AddAsync(ringGoExemptionMessage); //throw Null exception: 
    

Error

xUnit Test

private readonly Mock<IAsyncCollector<Message>> servicebusMessage;

[Fact]
public void 
Function_ShouldReturn_SuccessResponseResultObject_WhenSuccess()

        //Arrange
        var fixture = new Fixture();

        var ringGoTransaction = GetRingGoTestData();

        Mock<HttpRequest> mockHttpRequest = CreateMockRequest(ringGoTransaction);

        var providerLocationDataMoq = (1, fixture.Create<ProviderLocation>());

        providerExemptionServiceMoq.Setup(x => x.GetProviderLocation(13, "222")).ReturnsAsync(providerLocationDataMoq);

        //Assert
          var actualResult = sut.Run(mockHttpRequest.Object, (IAsyncCollector<Microsoft.Azure.ServiceBus.Message>)servicebusMessage.Object);  //???????????

        //Act
 

Test Helper Class

private static Mock<HttpRequest> CreateMockRequest(object body)

        var memoryStream = new MemoryStream();
        var writer = new StreamWriter(memoryStream);

        var json = JsonConvert.SerializeObject(body);

        writer.Write(json);
        writer.Flush();

        memoryStream.Position = 0;

        var mockRequest = new Mock<HttpRequest>();
        mockRequest.Setup(x => x.Body).Returns(memoryStream);
        mockRequest.Setup(x => x.ContentType).Returns("application/json");

        return mockRequest;
 

mock service bus error

【问题讨论】:

【参考方案1】:

我没有看到你在哪里嘲笑IAsyncCollector&lt;Message&gt;

它看起来像一个界面

public interface IAsyncCollector<in T>

    /// <summary>
    /// Adds an item to the <see cref="IAsyncCollectorT"/>.
    /// </summary>
    /// <param name="item">The item to be added.</param>
    /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
    /// <returns>A task that will add the item to the collector.</returns>
    Task AddAsync(T item, CancellationToken cancellationToken = default(CancellationToken));

    /// <summary>
    /// Flush all the events accumulated so far. 
    /// This can be an empty operation if the messages are not batched. 
    /// </summary>
    /// <param name="cancellationToken">The token to monitor for cancellation requests.</param>
    /// <returns></returns>
    Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken));

Source

所以new Mock&lt;IAsyncCollector&lt;Message&gt;&gt;() 和设置用于执行测试的成员应该足够简单

例如

[Fact]
public async Task Function_ShouldReturn_SuccessResponseResultObject_WhenSuccess() 
    //Arrange

    //... removed for brevity

    Mock<IAsyncCollector<Message>> servicebusMessage = new Mock<IAsyncCollector<Message>>();
    servicebusMessage
        .Setup(_ => _.AddAsync(It.IsAny<Message>(), It.IsAny<CancellationToken>()))
        .Returns(Task.CompletedTask);

    //Act
    await sut.Run(mockHttpRequest.Object, servicebusMessage.Object);  

    //Assert

    //...

鉴于被测对象的异步特性,请注意测试用例也已异步化。

【讨论】:

以上是关于在 Azure Function 中使用 xUnit 的 Moq 服务总线的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Azure Function 中使用 Azure Managed Identity 通过触发器访问 Service Bus?

在 Azure Function 中使用 xUnit 的 Moq 服务总线

如何在 Azure Function v2(核心)中静态使用 ConfigurationBuilder?

如何在启动类中使用 Azure Function 中的中间件

如何在本地环境中自动启动 Azure Function?

使用托管标识从 Azure Logic 应用向 Azure Function 进行身份验证