当前位置 : 主页 > 网络编程 > net编程 >

.NET6之MiniAPI(二十九):UnitTest

来源:互联网 收集:自由互联 发布时间:2023-09-03
MiniAPI的单元测试与asp.net webapi的单元测试大体是相同的(毕竟都是asp.net core),只是在小细节上有一些差异,文章中会说到这点。 本文测试框架是XUnit,Mock框架是Moq,关于这两个框架和

  MiniAPI的单元测试与asp.net web api的单元测试大体是相同的(毕竟都是asp.net core),只是在小细节上有一些差异,文章中会说到这点。

  本文测试框架是XUnit,Mock框架是Moq,关于这两个框架和库的学习,这里就忽略了。

  首先创建两个项目,API项目MiniAPI19UnitTest,UnitTest项目MiniAPI19UnitTestUT,如下:

  MiniAPI19UnitTest

var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IOrderService, OrderService>();
var app = builder.Build();

app.MapGet("/order", (IOrderService orderService) =>
{
return "Result:" + orderService.GetOrder("123");
});
app.MapPost("/order", (Order order, IOrderService orderService) =>
{
return "Result:" + orderService.AddOrder(order);
});
app.Run();

public interface IOrderService
{
bool AddOrder(Order order);
string GetOrder(string orderNo);
}
public class OrderService : IOrderService
{
private readonly ILogger<OrderService> _logger;
public OrderService(ILogger<OrderService> logger)
{
_logger = logger;
}
public string GetOrder(string orderNo)
{
return "this is my order,orderno:" + orderNo;
}
public bool AddOrder(Order order)
{
_logger.LogInformation(order.ToString());
return true;
}
}
public record Order
{
public string OrderNo { get; set; }
public string Name { get; set; }
public decimal Price { get; set; }
}

  MiniAPI19UnitTestUT:在本项目中添加引用MiniAPI19UnitTest项目

using Microsoft.AspNetCore.Mvc.Testing;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Moq;
using System;
using System.Net.Http;
using System.Threading.Tasks;
using Xunit;
namespace MiniAPI19UnitTestUT
{
public class MiniAPI19Test
{
[Fact]//无参测试
public async Task GetOrderTest()
{
var orderNo = "abcd";
//用Moq来mock server接口,达到层的隔离
var mock = new Mock<IOrderService>();
mock.Setup(x => x.GetOrder(It.IsAny<string>())).Returns(orderNo);
var myapp = new MyAppHostTest(services => services.AddSingleton(mock.Object));
var client = myapp.CreateClient();
var result = await client.GetStringAsync("/order");
Assert.Equal($"Result:{orderNo}", result);
}

[Theory]//有参测试
[InlineData(true)]
[InlineData(false)]
public async Task PostOrderTest(bool backResult)
{
var mock = new Mock<IOrderService>();
mock.Setup(x => x.AddOrder(It.IsAny<Order>())).Returns(backResult);
var myapp = new MyAppHostTest(services => services.AddSingleton(mock.Object));
var client = myapp.CreateClient();
var content = new StringContent(System.Text.Json.JsonSerializer.Serialize(new Order{OrderNo = "abcd",Name = "Surface Pro 8",Price = 10000}),System.Text.Encoding.UTF8,"application/json");
var response = await client.PostAsync("/order", content);
var result = await response.Content.ReadAsStringAsync();
Assert.Equal($"Result:{backResult}", result);
}
}
//本类是加构我们MiniAPI web host的类型,封装后以供测试程序调用
class MyAppHostTest : WebApplicationFactory<Program>
{
private readonly Action<IServiceCollection> _services;
public MyAppHostTest(Action<IServiceCollection> services)
{
_services = services;
}
protected override IHost CreateHost(IHostBuilder builder)
{
builder.ConfigureServices(_services);
return base.CreateHost(builder);
}
}
}

  上面的代码会报错,找不到Program的,这是因为API项目是用Top Level的方式来开发的,Program的访问修饰符是internal,虽然添加引用了MiniAPI19UnitTest项目,但Program是访问不到的,这里有两个解决方案,要么不用Top Level,如下面这样写代码:

public class Program
{
static void Main(string[] args)
{
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddScoped<IOrderService, OrderService>();
var app = builder.Build();
app.MapGet("/test", (IOrderService orderService) =>
{
return "Result:" + orderService.GetOrder("123");
});
app.Run();
}
}

  或者在MiniAPI19UnitTest.csproj文件中添加如下配置,让测试项目能访问到Program

<ItemGroup>
<InternalsVisibleTo Include="MiniAPI19UnitTestUT"/>
</ItemGroup>

  用反射工具查看API项目结果如下,Main函数是Top-Level Entry Point方式,也看不到Program

.NET6之MiniAPI(二十九):UnitTest_UnitTest

   这时,就可以开心地写自己的单元测试了。

  想要更快更方便的了解相关知识,可以关注微信公众号 

.NET6之MiniAPI(二十九):UnitTest_单元测试_02

 

上一篇:.NET6之MiniAPI(三十):结束篇
下一篇:没有了
网友评论