Как написать модульный тест для azure function v1

#c# #unit-testing #azure-functions #mstest

#c# #модульное тестирование #azure-функции #mstest

Вопрос:

Я написал функцию Azure v1 HttpTrigger, которая получает сведения о клиенте и транзакциях из нашего сервиса api, есть только один параметр, который является «частотой», который также необязателен, поэтому, когда функция запускается, она получает детали, затем получает транзакции для каждой информации о продавце и возвращает список комиссий за транзакции для каждого продавца, я хочу написать модульный тест для моей функции, но я не могу увидеть хороший пример для моего сценария, может кто-нибудь дать мне пример модульного теста (с moq, если возможно), вот функция пример кодовой базы:

 [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://learn.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 : Трассировка программы завершилась с кодом 0 (0x0).

С уважением,
Нико

Ответ №1:

Здесь я привожу пример модульного теста с вспомогательной функцией.

Тестовый пример:- Вспомогательная функция Request_With_Query:- HttpReuqestSetup (путем переноса HttprequestObject)

Я отметил, что издевался над объектом logger, поскольку это могло бы помочь мне предоставить полезную информацию

Вот как выглядит моя функция

  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)resu<
            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)resu<
            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)resu<
            Assert.AreEqual("Please pass a name on the query string or in the request body", resultObject.Value);
        }
    }
  

Вот вспомогательные классы

с помощью Microsoft.AspNetCore.Http; с использованием Microsoft.AspNetCore.Http.Внутренний; с использованием Microsoft.Azure.WebJobs; с использованием Microsoft.Azure.Веб-задания.Хост; с использованием Microsoft.Расширения.Примитивы; использование Moq; использование System; использование System.Коллекции.Общий; с использованием System.Ввод-вывод; с использованием System.Net.Http; с использованием System.Text; с использованием System.Многопоточность; использование System.Многопоточность.Задачи;

 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.

Надеюсь, это поможет.