创建测试项目
项目解决方案上右键,添加---->新建项目,选择适合自己的测试项目,点击【下一步】。我选的xUnit
单元测试类,创建项目后,自动生成的
using HL.Web.Api;
using HL.Web.Api.Services;
using HL.Web.Platform.Configure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using System.Configuration;
using System.Reflection;
using Microsoft.Extensions.Logging.Console;
using Microsoft.Extensions.Logging.Debug;
using NLog.Web;
using NLog.Extensions.Logging;
using System.Diagnostics;
using HL.Web.Api.Entity.Model.Collect;
using HL.Web.Api.Services.Impl;
namespace TestProject1
{
/// <summary>
/// 单元测试
/// </summary>
/// <remarks>
/// 创建2025-6-17 17:25:43,作者:wanghaoli
/// </remarks>
public class UnitTest1
{
IServiceProvider serviceProvider;
private IConfiguration configuration;
public UnitTest1()
{
//获取web项目的appsettings.json文件路径
string currentDirectory = AppDomain.CurrentDomain.BaseDirectory;
string bin = currentDirectory.Substring(0, currentDirectory.LastIndexOf("bin"));
bin = bin.TrimEnd('\\');
//解决方案目录
string slnProject = Directory.GetParent(bin).FullName;
var dir = Directory.GetDirectories(slnProject);
string? configJsonfilePath = null;
foreach (var item in dir)
{
var files = Directory.GetFiles(item);
if (files.Length == 0)
{
continue;
}
configJsonfilePath = files.FirstOrDefault(g => g.Contains("appsettings.json"));
if (!string.IsNullOrWhiteSpace(configJsonfilePath))
{
break;
}
}
//加载配置文件
configuration = new ConfigurationBuilder()
.AddJsonFile(configJsonfilePath)
.Build();
ServiceCollection serviceCollection = new ServiceCollection();
ConfigureServices.AddServices(serviceCollection);
ConfigureServices.AddSqlsugarSetup(serviceCollection, configuration);
serviceCollection.AddLogging(builder =>
{
builder.ClearProviders();
builder.AddConsole();
builder.AddDebug();
//builder.SetMinimumLevel(LogLevel.Debug);
//builder.AddFilter("Logs/log_{Date}.txt"); // 注册 File 提供程序
});
//自动注册接口、实例
InjectUtil.InitServe(serviceCollection);
serviceProvider = serviceCollection.BuildServiceProvider();
}
/// <summary>
/// 单条写入
/// </summary>
/// <returns></returns>
[Fact]
public async Task Insert()
{
var collectionDataService = serviceProvider.GetService<ICollectionDataService>();
SinterEquipmentCollect info = new SinterEquipmentCollect();
info.SingleId = 556;
info.SingleName = "测试设备556";
long snowId = await collectionDataService.InsertAsync(info);
Assert.Equal(snowId.ToString().Length, 19);
}
/// <summary>
/// 批量写入
/// </summary>
/// <returns></returns>
[Fact]
public async Task InsertList()
{
var collectionDataService = serviceProvider.GetService<ICollectionDataService>();
List<SinterEquipmentCollect> list = new();
for (int i = 0; i < 10; i++)
{
SinterEquipmentCollect info = new SinterEquipmentCollect();
info.SingleId = 100 + i;
info.SingleName = "测试设备" + info.SingleId;
list.Add(info);
}
int count = await collectionDataService.InsertListAsync(list);
Assert.True(count>0);
}
}
}
InjectUtil.cs
using HL.Web.Api;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestProject1
{
/// <summary>
/// 依赖注入,工具
/// </summary>
/// <remarks>
/// 创建时间:2025-6-17 16:36:43,作者:王浩力
/// </remarks>
public sealed class InjectUtil
{
/// <summary>
/// 自动注册接口、实例
/// </summary>
/// <param name="services"></param>
/// <param name="serviceLifetime"></param>
public static void InitServe(ServiceCollection services, ServiceLifetime serviceLifetime = ServiceLifetime.Scoped)
{
List<Type> types = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(w => w.GetCustomAttributes(typeof(ServiceAttribute), false).Length > 0
&& w.IsClass && w.IsAbstract != true)
.ToList();
foreach (Type type in types)
{
Type[] interfaces = type.GetInterfaces();
interfaces.ToList().ForEach(x =>
{
switch (serviceLifetime)
{
case ServiceLifetime.Singleton:
services.AddSingleton(x, type);
break;
case ServiceLifetime.Scoped:
services.AddScoped(x, type);
break;
case ServiceLifetime.Transient:
services.AddTransient(x, type);
break;
}
});
}
}
}
}
ConfigureServices.cs
using System.Reflection;
using HL.Model.Attributes;
using HL.Web.Api;
using HL.Web.Api.Common.Consts;
using HL.Web.Api.JobServices;
using HL.Web.Platform.Filter;
using Quartz;
using SqlSugar;
namespace HL.Web.Platform.Configure
{
/// <summary>
/// 配置服务
/// </summary>
public static class ConfigureServices
{
/// <summary>
/// 添加SqlSugar
/// </summary>
/// <param name="services"></param>
/// <param name="config"></param>
public static void AddSqlsugarSetup(this IServiceCollection services, IConfiguration config)
{
//读取数据库连接
var collectDbConn = config.GetSection(DbConnectionConst.CollectDbConn).Value;
var analysisDbConn = config.GetSection(DbConnectionConst.AnalysisDbConn).Value;
//注入事务过滤器
services.AddScoped<TransactionFilter>();
//注册上下文:AOP里面可以获取IOC对象,如果有现成框架比如Furion可以不写这一行
services.AddHttpContextAccessor();
//实体、字段映射
ConfigureExternalServices configureExternalServices = new ConfigureExternalServices
{
EntityService = (property, column) =>
{
var ColumnInfo = property.GetCustomAttribute<ColumnInfoAttribute>();
if (ColumnInfo != null)
{
column.IsPrimarykey = ColumnInfo.IsPrimarykey;
column.DbColumnName = ColumnInfo.DbColumnName;
column.ColumnDescription = ColumnInfo.ColumnDescription;
column.IsNullable = ColumnInfo.IsNullable;
column.IsOnlyIgnoreUpdate = ColumnInfo.IsOnlyIgnoreUpdate;
column.IsJson = ColumnInfo.IsJson;
column.DataType = ColumnInfo.DataType;
column.SqlParameterDbType = ColumnInfo.SqlParameterDbType;
column.IsEnableUpdateVersionValidation = ColumnInfo.IsEnableUpdateVersionValidation;
column.IsIgnore = ColumnInfo.IsIgnore;
column.Length = ColumnInfo.Length;
}
else
{
//最好排除DTO类
column.DbColumnName = UtilMethods.ToUnderLine(column.DbColumnName);//ToUnderLine驼峰转下划线方法
column.IsNullable = true;
}
},
EntityNameService = (type, entity) =>
{
var tableInfo = type.GetCustomAttribute<TableInfoAttribute>();
if (tableInfo != null)
{
entity.DbTableName = tableInfo.DbTableName;
entity.TableDescription = tableInfo.TableDescription;
}
else
{
//最好排除DTO类
entity.DbTableName = UtilMethods.ToUnderLine(entity.DbTableName);//ToUnderLine驼峰转下划线方法
}
}
};
//注册SqlSugar
services.AddTransient<ISqlSugarClient>(client =>
{
SqlSugarScope sqlSugar = new SqlSugarScope(new List<ConnectionConfig>
{
new ConnectionConfig(){ ConfigId = DbConnectionConst.CollectDbConn, DbType = DbType.SqlServer, ConnectionString = collectDbConn, IsAutoCloseConnection = true, ConfigureExternalServices = configureExternalServices },
new ConnectionConfig(){ ConfigId = DbConnectionConst.AnalysisDbConn, DbType = DbType.SqlServer, ConnectionString = analysisDbConn, IsAutoCloseConnection = true, ConfigureExternalServices = configureExternalServices }
}
,
db =>
{
var serviceBuilder = services.BuildServiceProvider();
var logger = serviceBuilder.GetService<ILogger<ApiControllerBase>>();
//SQL执行完
db.Aop.OnLogExecuted = (sql, pars) =>
{
//执行完了可以输出SQL执行时间 (OnLogExecutedDelegate)
logger?.LogInformation($"ExecutedTime:{db.Ado.SqlExecutionTime}");
string sql2 = UtilMethods.GetNativeSql(sql, pars);
LogHelpter.AddLog($"{sql2}" );
};
//单例参数配置,所有上下文生效
db.Aop.OnLogExecuting = (sql, pars) =>
{
获取作IOC作用域对象
//var appServive = s.GetService<IHttpContextAccessor>();
//var obj = appServive?.HttpContext?.RequestServices.GetService<ILogger>();
//Console.WriteLine("AOP" + obj?.GetHashCode());
sql = UtilMethods.GetNativeSql(sql, pars);
logger?.LogInformation(sql);
};
db.Aop.OnError = (exp) =>//SQL报错
{
//获取原生SQL推荐 5.1.4.63 性能OK
UtilMethods.GetNativeSql(exp.Sql, exp.Parametres as SugarParameter[]);
};
db.Aop.OnExecutingChangeSql = (sql, pars) => //可以修改SQL和参数的值
{
//sql=newsql
//foreach(var p in pars) //修改
return new KeyValuePair<string, SugarParameter[]>(sql, pars);
};
db.Aop.DataExecuting = (oldValue, entityInfo) =>
{
};
});
return sqlSugar;
});
}
}
}