首页 > 其他分享 >.NET6之MiniAPI(二十九):UnitTest

.NET6之MiniAPI(二十九):UnitTest

时间:2022-11-30 20:56:22浏览次数:40  
标签:MiniAPI builder UnitTest public services using var NET6 order

  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

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

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

 

 

标签:MiniAPI,builder,UnitTest,public,services,using,var,NET6,order
From: https://www.cnblogs.com/axzxs2001/p/16939692.html

相关文章

  • .NET6之MiniAPI(三十):结束篇
    不知不觉来到了《.NET6之MiniAPI》的第三十篇,回顾之前的篇幅,主要涉及如下:HTTP请求,应答(二,三)配置选项(四,五)依赖注入,中间件(六,七)日志,监控,跟踪,健康检查(八,十三,十......
  • .NET6之MiniAPI(二十八):Tracing
    Log,Metrics,Tracing是为服务正常运行保驾护航的三件套,前面有介绍过Log和Metrics,本篇说明说一下Tracing。Tracing的思路和Metrics一样,通过三方服务,来达成效果,这里选用的......
  • .NET6之MiniAPI(二十七):Metrics
    应用的各种Metrics是保证应用健康稳定运行的基础,特别对于一些可用性有所要求的应用,本文介绍prometheus-net这个三方指示库。prometheus-net的工作原理是,在应用内......
  • .NET6之MiniAPI(二十七):Metrics
    应用的各种Metrics是保证应用健康稳定运行的基础,特别对于一些可用性有所要求的应用,本文介绍prometheus-net这个三方指示库。prometheus-net的工作原理是,在应用内......
  • .NET6之MiniAPI(特别篇):.NET7 Preview1&2
    在写.NET6MiniAPI的时候,.NET7的新功能也在发展,这里就用特别篇把新加的特点分享给大家,本篇先说Preview1和2特点1文件上传,demo如下:varbuilder=WebApplication......
  • .NET6之MiniAPI(特别篇):.NET7 Preview1&2
    在写.NET6MiniAPI的时候,.NET7的新功能也在发展,这里就用特别篇把新加的特点分享给大家,本篇先说Preview1和2特点1文件上传,demo如下:varbuilder=WebApplic......
  • .NET6之MiniAPI(二十五):Dapper
    注:如果你使用Dapper一段时间了,这篇你可以跳过去了。在第十二篇中,我们聊过官方的ORM——EntityFramework,它可以把SQL细节都隐藏,这对于一些标准化的关系数据库项目......
  • .NET6之MiniAPI(特别篇):.NET7 Preview1&2
    在写.NET6MiniAPI的时候,.NET7的新功能也在发展,这里就用特别篇把新加的特点分享给大家,本篇先说Preview1和2特点1文件上传,demo如下:varbuilder=WebApplic......
  • .net core .net6 webapi 连接mysql 8
    1.表结构:CREATETABLE`table2`(`id`BIGINTNOTNULLAUTO_INCREMENT,`myname`varchar(255)NOTNULL,`create_time`DATETIMENOTNULL,PRIMARYKEY(`......
  • .NET6之MiniAPI(二十四):用Polly重试
    为了保障系统的稳定和安全,在调用三方服务时,可以增加重试和熔断。重试是调用一次失败后再试几试,避免下游服务一次闪断,就把整个链路终止;熔断是为了防止太多的次数的无效访......