简体   繁体   中英

How to write unit test for azure function v1

I wrote an azure function v1 HttpTrigger that gets client details and transactions from our api service, there is only one parameter which is "frequency" which is optional also, so when the function is triggered it will get the details then get transactions for each retailer details and returns a list of transaction fee for each retailer, I want to write a unit test for my function but I am not able to see a good example for my scenario , Can someone give me an example unit test (with moq if possible) , here is the function codebase example:

[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")
            };
    } 

References for unit test I tried: 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

What I tried:

[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);
    }

Errors I got:
The thread 0x5580 has exited with code 0 (0x0).
The program '[23748] dotnet.exe' has exited with code 0 (0x0).
The program '[23748] dotnet.exe: Program Trace' has exited with code 0 (0x0).

Regards,
Nico

Here I am giving sample unit test case with a helper function.

Test Case:- Request_With_Query Helper Function:- HttpReuqestSetup ( by mokcing HttprequestObject)

I have note mocked the logger object as it could help me with giving useful information

This is how my function looks like

 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");
        }

    }

and this is how my test class looks like:

[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);
        }
    }

Here is the Helper classes

using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http.Internal; using Microsoft.Azure.WebJobs; using Microsoft.Azure.WebJobs.Host; using Microsoft.Extensions.Primitives; using Moq; using System; using System.Collections.Generic; using System.IO; using System.Net.Http; using System.Text; using System.Threading; using 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);
        }
    }

Use the similar pattern in your case, you should be able to mock and write UT's peacefully.

Hope it helps.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM