#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.
Надеюсь, это поможет.