在 Azure Function 中使用 xUnit 的 Moq 服务总线
Moq Service Bus using xUnit in Azure Function
我有 Azure Function,它实现了 HTTP 触发器和服务总线。我已经设法完成了 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
我没看到你在哪里嘲笑 IAsyncCollector<Message>
。
看起来像一个界面
public interface IAsyncCollector<in T>
{
/// <summary>
/// Adds an item to the <see cref="IAsyncCollector{T}"/>.
/// </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));
}
所以 new Mock<IAsyncCollector<Message>>()
和设置用于练习测试的成员应该足够简单
例如
[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,它实现了 HTTP 触发器和服务总线。我已经设法完成了 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
我没看到你在哪里嘲笑 IAsyncCollector<Message>
。
看起来像一个界面
public interface IAsyncCollector<in T>
{
/// <summary>
/// Adds an item to the <see cref="IAsyncCollector{T}"/>.
/// </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));
}
所以 new Mock<IAsyncCollector<Message>>()
和设置用于练习测试的成员应该足够简单
例如
[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
//...
}
鉴于被测对象的异步性质,请注意测试用例也已异步化。