【问题标题】:How to write unit test for azure function v1如何为 azure function v1 编写单元测试
【发布时间】:2019-03-19 01:04:11
【问题描述】:

我写了一个 azure 函数 v1 HttpTrigger 从我们的 api 服务获取客户端详细信息和事务,只有一个参数“频率”也是可选的,所以当函数被触发时,它将获取详细信息然后获取事务对于每个零售商的详细信息并返回每个零售商的交易费用列表,我想为我的功能编写一个单元测试,但我看不到我的场景的一个很好的例子,有人可以给我一个示例单元测试(带起订量如果可能),这里是函数代码库示例:

[FunctionName("FunctionTest1")]
public static async Task<HttpResponseMessage> 
Run([HttpTrigger(AuthorizationLevel.Function)]HttpRequestMessage req, ILogger log) {
        log.LogInformation("C# HTTP trigger function processed a request.");
        #region Properties
        string Frequency = req.GetQueryNameValuePairs().FirstOrDefault(q => string.Compare(q.Key, "frequency", true) == 0).Value;
        #endregion

        log.LogInformation("Getting client details from MongoDB");
        Process of Getting ClientDetails

        log.LogInformation("Get and compute Transaction Fee foreach retailers from client details");
        Process of Getting And Computing Transactions for each retailers (NOTE Took too much time)


        log.LogInformation("Return results response");
        return txnList == null
            ? new HttpResponseMessage(HttpStatusCode.InternalServerError) {
                Content = new StringContent(JsonConvert.SerializeObject("Error getting data from server"), Encoding.UTF8, "application/json")
            } : new HttpResponseMessage(HttpStatusCode.OK) {
                Content = new StringContent(JsonConvert.SerializeObject(txnList, Newtonsoft.Json.Formatting.Indented), Encoding.UTF8, "application/json")
            };
    } 

我试过的单元测试参考:https://docs.microsoft.com/en-us/azure/azure-functions/functions-test-a-function
https://medium.com/@tsuyoshiushio/writing-unit-test-for-azure-durable-functions-80f2af07c65e

我尝试了什么:

[TestMethod]
    public async Task Response_Should_Not_Null()
    {
        var request = new HttpRequestMessage();

        var logger = Mock.Of<ILogger>();

        var response = await FunctionTest1.Run(request, logger).ConfigureAwait(false);

        Assert.IsNotNull(response);
    }

我遇到的错误:
线程 0x5580 已退出,代码为 0 (0x0)。
程序“[23748] dotnet.exe”已退出,代码为 0 (0x0)。
程序“[23748] dotnet.exe: Program Trace”已退​​出,代码为 0 (0x0)。

问候,
妮可

【问题讨论】:

    标签: c# unit-testing azure-functions mstest


    【解决方案1】:

    这里我给出了一个带有辅助函数的示例单元测试用例。

    测试用例:- Request_With_Query 辅助函数:- HttpReuqestSetup(通过模拟 HttprequestObject)

    我注意到模拟了记录器对象,因为它可以帮助我提供有用的信息

    这就是我的函数的样子

     public static class HttpTrigger
        {
            [FunctionName("HttpTrigger")]
            public async static Task<IActionResult> RunAsync([HttpTrigger(AuthorizationLevel.Function, "get", "post", Route = null)]HttpRequest req, TraceWriter log)
            {
                log.Info("C# HTTP trigger function processed a request.");
    
                string name = req.Query["name"];
    
                string requestBody = new StreamReader(req.Body).ReadToEnd();
                dynamic data = JsonConvert.DeserializeObject(requestBody);
                name = name ?? data?.name;
    
                return name != null
                    ? (ActionResult)new OkObjectResult($"Hello, {name}")
                    : new BadRequestObjectResult("Please pass a name on the query string or in the request body");
            }
    
        }
    

    这就是我的测试类的样子:

    [TestClass]
        public class HttpTriggerTest : FunctionTestHelper.FunctionTest
        {
            [TestMethod]
            public async Task Request_With_Query()
            {
                var query = new Dictionary<String, StringValues>();
                query.TryAdd("name", "ushio");
                var body = "";
    
                var result = await HttpTrigger.RunAsync(req: HttpRequestSetup(query, body), log: log);
                var resultObject = (OkObjectResult)result;
                Assert.AreEqual("Hello, ushio", resultObject.Value);
    
            }
    
            [TestMethod]
            public async Task Request_Without_Query()
            {
                var query = new Dictionary<String, StringValues>();
                var body = "{\"name\":\"yamada\"}";
    
                var result = await HttpTrigger.RunAsync(HttpRequestSetup(query, body), log);
                var resultObject = (OkObjectResult)result;
                Assert.AreEqual("Hello, yamada", resultObject.Value);
    
            }
    
            [TestMethod]
            public async Task Request_Without_Query_And_Body()
            {
                var query = new Dictionary<String, StringValues>();
                var body = "";
                var result = await HttpTrigger.RunAsync(HttpRequestSetup(query, body), log);
                var resultObject = (BadRequestObjectResult)result;
                Assert.AreEqual("Please pass a name on the query string or in the request body", resultObject.Value);
            }
        }
    

    这里是 Helper 类

    使用 Microsoft.AspNetCore.Http; 使用 Microsoft.AspNetCore.Http.Internal; 使用 Microsoft.Azure.WebJobs; 使用 Microsoft.Azure.WebJobs.Host; 使用 Microsoft.Extensions.Primitives; 使用最小起订量; 使用系统; 使用 System.Collections.Generic; 使用 System.IO; 使用 System.Net.Http; 使用 System.Text; 使用 System.Threading; 使用 System.Threading.Tasks;

    namespace FunctionTestHelper
    {
        public abstract class FunctionTest
        {
    
            protected TraceWriter log = new VerboseDiagnosticsTraceWriter();
    
            public HttpRequest HttpRequestSetup(Dictionary<String, StringValues> query, string body)
            {
                var reqMock = new Mock<HttpRequest>();
    
                reqMock.Setup(req => req.Query).Returns(new QueryCollection(query));
                var stream = new MemoryStream();
                var writer = new StreamWriter(stream);
                writer.Write(body);
                writer.Flush();
                stream.Position = 0;
                reqMock.Setup(req => req.Body).Returns(stream);
                return reqMock.Object;
            }
    
        }
    
        public class AsyncCollector<T> : IAsyncCollector<T>
        {
            public readonly List<T> Items = new List<T>();
    
            public Task AddAsync(T item, CancellationToken cancellationToken = default(CancellationToken))
            {
    
                Items.Add(item);
    
                return Task.FromResult(true);
            }
    
            public Task FlushAsync(CancellationToken cancellationToken = default(CancellationToken))
            {
                return Task.FromResult(true);
            }
        }
    }
    
    public class VerboseDiagnosticsTraceWriter : TraceWriter
        {
    
            public VerboseDiagnosticsTraceWriter() : base(TraceLevel.Verbose)
            {
    
            }
            public override void Trace(TraceEvent traceEvent)
            {
                Debug.WriteLine(traceEvent.Message);
            }
        }
    

    在你的情况下使用类似的模式,你应该能够和平地模拟和编写 UT。

    希望对你有帮助。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-01-17
      • 2012-01-06
      • 2019-03-17
      • 2016-04-02
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多