gpt4 book ai didi

.net - 在 .NET 5 中测试 Azure 函数

转载 作者:行者123 更新时间:2023-12-02 22:48:47 24 4
gpt4 key购买 nike

我已经开始开发 Azure Functions,现在我想创建我的第一个单元/集成测试,但我完全陷入困境。虽然我有一个非常简单的函数,带有 HTTP 触发器、HTTP 和存储队列输出,但测试它似乎非常复杂。

代码(简化):

public class MyOutput
{
[QueueOutput("my-queue-name", Connection = "my-connection")]
public string QueueMessage { get; set; }

public HttpResponseData HttpResponse { get; set; }
}

public static class MyFunction
{
[Function(nameof(MyFunction))]
public static async Task<MyOutput> Run(
[HttpTrigger(AuthorizationLevel.Function, "POST")] HttpRequestData req,
FunctionContext executionContext)
{
var logger = executionContext.GetLogger(nameof(MyFunction));
logger.LogInformation("Received {Bytes} bytes", req.Body.Length);
//implementation
}
}

现在我希望构建这样的测试:

public async Task Test()
{
var response = await MyFunction.Run(..., ...);
Assert.IsNotNull(response);
}

在互联网上寻找了几个小时的好方法后,我仍然没有找到模拟 HttpRequestDataFunctionContext 的方法。我还通过设置服务器来寻找完整的集成测试,但这看起来非常复杂。我最终得到的唯一结果是:https://github.com/Azure/azure-functions-dotnet-worker/blob/72b9d17a485eda1e6e3626a9472948be1152ab7d/test/E2ETests/E2ETests/HttpEndToEndTests.cs

是否有人有在 .NET 5 中测试 Azure Functions 的经验,谁可以帮助我朝正确的方向前进?有没有关于如何在 dotnet-isolated 中测试 Azure Function 的好文章或示例?

最佳答案

解决方案1

我终于能够 mock 整件事了。绝对不是我最好的作品,可以使用一些重构,但至少我得到了一个工作原型(prototype):

var serviceCollection = new ServiceCollection();
serviceCollection.AddScoped<ILoggerFactory, LoggerFactory>();
var serviceProvider = serviceCollection.BuildServiceProvider();

var context = new Mock<FunctionContext>();
context.SetupProperty(c => c.InstanceServices, serviceProvider);

var byteArray = Encoding.ASCII.GetBytes("test");
var bodyStream = new MemoryStream(byteArray);

var request = new Mock<HttpRequestData>(context.Object);
request.Setup(r => r.Body).Returns(bodyStream);
request.Setup(r => r.CreateResponse()).Returns(() =>
{
var response = new Mock<HttpResponseData>(context.Object);
response.SetupProperty(r => r.Headers, new HttpHeadersCollection());
response.SetupProperty(r => r.StatusCode);
response.SetupProperty(r => r.Body, new MemoryStream());
return response.Object;
});

var result = await MyFunction.Run(request.Object, context.Object);
result.HttpResponse.Body.Seek(0, SeekOrigin.Begin);
var reader = new StreamReader(result.HttpResponse.Body);
var responseBody = await reader.ReadToEndAsync();

Assert.IsNotNull(result);
Assert.AreEqual(HttpStatusCode.OK, result.HttpResponse.StatusCode);
Assert.AreEqual("Hello test", responseBody);

解决方案2

我通过依赖注入(inject)添加了记录器,并为 HttpRequestDataHttpResponseData 创建了自己的实现。这更容易重用,并使测试本身更干净。

public class FakeHttpRequestData : HttpRequestData
{
public FakeHttpRequestData(FunctionContext functionContext, Uri url, Stream body = null) : base(functionContext)
{
Url = url;
Body = body ?? new MemoryStream();
}

public override Stream Body { get; } = new MemoryStream();

public override HttpHeadersCollection Headers { get; } = new HttpHeadersCollection();

public override IReadOnlyCollection<IHttpCookie> Cookies { get; }

public override Uri Url { get; }

public override IEnumerable<ClaimsIdentity> Identities { get; }

public override string Method { get; }

public override HttpResponseData CreateResponse()
{
return new FakeHttpResponseData(FunctionContext);
}
}

public class FakeHttpResponseData : HttpResponseData
{
public FakeHttpResponseData(FunctionContext functionContext) : base(functionContext)
{
}

public override HttpStatusCode StatusCode { get; set; }
public override HttpHeadersCollection Headers { get; set; } = new HttpHeadersCollection();
public override Stream Body { get; set; } = new MemoryStream();
public override HttpCookies Cookies { get; }
}

现在测试看起来像这样:

// Arrange
var body = new MemoryStream(Encoding.ASCII.GetBytes("{ \"test\": true }"))
var context = new Mock<FunctionContext>();
var request = new FakeHttpRequestData(
context.Object,
new Uri("https://stackoverflow.com"),
body);

// Act
var function = new MyFunction(new NullLogger<MyFunction>());
var result = await function.Run(request);
result.HttpResponse.Body.Position = 0;

// Assert
var reader = new StreamReader(result.HttpResponse.Body);
var responseBody = await reader.ReadToEndAsync();
Assert.IsNotNull(result);
Assert.AreEqual(HttpStatusCode.OK, result.HttpResponse.StatusCode);
Assert.AreEqual("Hello test", responseBody);

关于.net - 在 .NET 5 中测试 Azure 函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67937686/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com