C# .net core添加单元测试项目,依赖注入接口测试
·
目录
创建测试项目
项目解决方案上右键,添加---->新建项目,选择适合自己的测试项目,点击【下一步】。我选的xUnit

UnitTest1.cs单元测试类,创建项目后,自动生成的
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;
using SqlSugar;
using System.Threading.Tasks;
namespace TestProject1
{
/// <summary>
/// 单元测试
/// </summary>
/// <remarks>
/// 创建2025-6-17 17:25:43,作者:王浩力
/// </remarks>
public class UnitTest1
{
private readonly IServiceProvider serviceProvider;
public UnitTest1()
{
serviceProvider = CommInject.InitIoc();
}
/// <summary>
/// 采集测试,写入数据
/// </summary>
/// <returns></returns>
[Fact]
public async Task Test1()
{
//// 从容器中获取日志记录器,测试无效无法记录日志
var logger = serviceProvider.GetRequiredService<ILogger<UnitTest1>>();
//var logger = serviceProvider.GetService<ILogger<UnitTest1>>();
logger.LogInformation("测试消息");
//logger.LogDebug("测试消息2");
//无效
//var loggerFactory = LoggerFactory.Create(loggingBuilder => loggingBuilder
//.AddConfiguration(configuration)
//.AddConsole());
//ILogger logger2 = loggerFactory.CreateLogger<UnitTest1>();
//logger2.LogInformation("测试消息3");
Stopwatch stopwatch = new Stopwatch();
stopwatch.Start();
LogHelpter.AddLog("任务开始....");
//var task1 = Task.Run(async () =>
//{
// var collectionData = serviceProvider.GetService<ICollectionData>();
// await collectionData.InsertTestAsync(DateTime.Now.AddDays(-3));
//});
//var task2 = Task.Run(async () =>
//{
// var collectionData = serviceProvider.GetService<ICollectionData>();
// await collectionData.InsertTestAsync(DateTime.Now.AddDays(-2));
//});
var task3 = Task.Run(async () =>
{
var collectionDataService = serviceProvider.GetService<ICollectionDataService>();
await collectionDataService.InsertTestAsync(DateTime.Now.AddDays(0));
});
//Task.WaitAll(task1, task2, task3);
//Task.WaitAll(task1, task3);
Task.WaitAll(task3);
stopwatch.Stop();
float seconds = stopwatch.ElapsedMilliseconds / 1000;
System.Diagnostics.Debug.WriteLine("任务完成,耗时秒=" + seconds);
LogHelpter.AddLog("任务完成,耗时秒=" + seconds);
}
/// <summary>
/// 单条写入
/// </summary>
/// <returns></returns>
[Fact]
public async Task Insert()
{
var collectionDataService = serviceProvider.GetService<ICollectionDataService>();
SinterEquipmentCollect info = new SinterEquipmentCollect();
info.SingleId = 756;
info.SingleName = "测试设备" + info.SingleId;
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);
}
[Fact]
private async Task AddEquipmentData()
{
//测试,写入,每分钟一次,更新设备数据;每台设备一条记录;
var equipmentService = serviceProvider.GetService<IEquipmentData>();
// await equipmentService.AddDataEquipmentCurrentDataAsync();
await equipmentService.AddEquipmentHistoryDataAsync();
}
}
}
怎么调试自己写的单元测试方法?
首先找到自己写的方法代码,鼠标点中方法代码段内,然后鼠标右键,可以点击(调试测试),就单独测试鼠标光标选中的方法;调试模式会命中打的断点;运行测试不会命中断点;

怎么测试一个单元测试类文件里面所有单元测试方法?
测试完成后,方法左侧标记的绿色勾,表示方法通过测试;否则没有通过测试;



举例的接口实例,类头部加了自定义的属性标记ServiceAttribute
/// <summary>
/// 采集数据,接口实现
/// </summary>
/// <remarks>
/// 创建时间:2025-6-17 15:30:46,作者:whl
/// </remarks>
[Service]
public class CollectionDataService : ICollectionDataService
{
private readonly ISqlSugarClient sugarClient;
public CollectionDataService(ISqlSugarClient _sqlSugarClient)
{
sugarClient = _sqlSugarClient;
}
}
namespace HL.Web.Api
{
/// <summary>
/// 服务特性。
/// </summary>
[AttributeUsage(AttributeTargets.Class)]
public class ServiceAttribute : Attribute
{
/// <summary>
/// 无参构造函数
/// </summary>
public ServiceAttribute()
{
}
}
}
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.Transient)
{
//这里可以使用自己的方式找到接口、实例的类集合。不一定非要在实现类上面打自定义属性标签。
//也可以通过类名的后缀查找类,或者类的命名空间查找等方式;
//比如实现类后缀为impl结尾,则可以用类名后缀查找;
List<Type> implList = AppDomain.CurrentDomain
.GetAssemblies()
.SelectMany(x => x.GetTypes())
.Where(w => w.GetCustomAttributes(typeof(ServiceAttribute), false).Length > 0
&& w.IsClass && w.IsAbstract != true)
.ToList();
foreach (Type impl in implList)
{
Type[] interfaces = impl.GetInterfaces();
interfaces.ToList().ForEach(interfaceT =>
{
switch (serviceLifetime)
{
case ServiceLifetime.Singleton:
services.AddSingleton(interfaceT, impl);
break;
case ServiceLifetime.Scoped:
services.AddScoped(interfaceT, impl);
break;
case ServiceLifetime.Transient:
services.AddTransient(interfaceT, impl);
break;
}
});
}
}
}
}
CommInject
using HL.Web.Platform.Configure;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using NLog.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace TestProject1
{
/// <summary>
/// 依赖注入初始化
/// </summary>
/// <remarks>
/// 创建时间:2025-6-18 17:53:09,王浩力
/// </remarks>
internal class CommInject
{
/// <summary>
/// 初始化容器
/// </summary>
/// <returns></returns>
public static IServiceProvider InitIoc()
{
IConfiguration configuration=null;
//获取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;
}
string jsonName = $"appsettings.Development.json";
#if (!DEBUG)
jsonName = $"appsettings.Staging.json";
#endif
LogHelpter.AddLog("配置文件="+ jsonName);
configJsonfilePath = files.FirstOrDefault(g => g.Contains(jsonName));
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 提供程序
});
serviceCollection.AddNLog();//日志组件实例
//自动注册接口、实例
InjectUtil.InitServe(serviceCollection);
return serviceCollection.BuildServiceProvider();
}
}
}
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;
});
}
}
}
更多推荐

所有评论(0)