完成新建设备的单元 测试包括,添加变量表,和添加菜单
This commit is contained in:
@@ -10,9 +10,11 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AutoMapper.Extensions.Microsoft.DependencyInjection" Version="12.0.1" />
|
||||
<PackageReference Include="Bogus" Version="35.6.3" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2025.1.0-eap1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="9.0.7" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="xunit" Version="2.5.3" />
|
||||
@@ -24,6 +26,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\DMS.Application\DMS.Application.csproj" />
|
||||
<ProjectReference Include="..\DMS.Infrastructure\DMS.Infrastructure.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -5,55 +5,142 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using DMS.Application.DTOs;
|
||||
using DMS.Core.Enums;
|
||||
using DMS.Core.Models;
|
||||
|
||||
namespace DMS.Infrastructure.UnitTests
|
||||
{
|
||||
public static class FakerHelper
|
||||
{
|
||||
public static DbDevice FakeDbDevice()
|
||||
public static Device FakeDevice()
|
||||
{
|
||||
var dbDevice = new Faker<DbDevice>()
|
||||
.RuleFor(d => d.Name, f => f.Commerce.ProductName())
|
||||
.RuleFor(d => d.Description, f => f.Commerce.ProductDescription())
|
||||
.RuleFor(d => d.IpAddress, f => f.Internet.Ip())
|
||||
.RuleFor(d => d.OpcUaServerUrl, f => f.Internet.Url())
|
||||
.Generate();
|
||||
var dbDevice = new Faker<Device>()
|
||||
.RuleFor(d => d.Name, f => f.Commerce.ProductName())
|
||||
.RuleFor(d => d.Description, f => f.Commerce.ProductDescription())
|
||||
.RuleFor(d => d.IpAddress, f => f.Internet.Ip())
|
||||
.RuleFor(d => d.OpcUaServerUrl, f => f.Internet.Url())
|
||||
.Generate();
|
||||
dbDevice.Port = 102;
|
||||
dbDevice.Protocol = ProtocolType.S7;
|
||||
dbDevice.Slot = 1;
|
||||
dbDevice.Rack = 0;
|
||||
dbDevice.CpuType = "S7-1200";
|
||||
dbDevice.DeviceType = Core.Enums.DeviceType.SiemensPLC;
|
||||
|
||||
|
||||
return dbDevice;
|
||||
}
|
||||
|
||||
public static DbVariableTable FakeDbVariableTable()
|
||||
public static VariableTable FakeVariableTable()
|
||||
{
|
||||
var dbVarTable = new Faker<DbVariableTable>()
|
||||
.RuleFor(d => d.Name, f => f.Commerce.ProductName())
|
||||
.RuleFor(d => d.Description, f => f.Commerce.ProductDescription())
|
||||
.Generate();
|
||||
dbVarTable.Protocol = ProtocolType.S7;
|
||||
dbVarTable.IsActive=true;
|
||||
return dbVarTable;
|
||||
var varTable = new Faker<VariableTable>()
|
||||
.RuleFor(d => d.Name, f => f.Commerce.ProductName())
|
||||
.RuleFor(d => d.Description, f => f.Commerce.ProductDescription())
|
||||
.Generate();
|
||||
varTable.IsActive = true;
|
||||
return varTable;
|
||||
}
|
||||
|
||||
// public static DbVariable FakeDbVariable()
|
||||
// {
|
||||
// var dbVariable = new Faker<DbVariable>()
|
||||
// .RuleFor(d => d.Name, f => f.Commerce.ProductName())
|
||||
// .RuleFor(d => d.Description, f => f.Commerce.ProductDescription())
|
||||
// .RuleFor(d => d.S7Address, f => f.Internet.DomainWord())
|
||||
// .RuleFor(d => d.DataValue, f => f.Commerce.Price())
|
||||
// .Generate();
|
||||
// dbVariable.ProtocolType = Core.Enums.ProtocolType.S7;
|
||||
// dbVariable.IsActive = true;
|
||||
// dbVariable.SignalType=Core.Enums.SignalType.RunSignal;
|
||||
// dbVariable.UpdateTime=DateTime.Now;
|
||||
// dbVariable.DataType = "String";
|
||||
// return dbVariable;
|
||||
// }
|
||||
|
||||
public static VariableTableDto FakeVariableTableDto()
|
||||
{
|
||||
var varTable = new Faker<VariableTableDto>()
|
||||
.RuleFor(d => d.Name, f => f.Commerce.ProductName())
|
||||
.RuleFor(d => d.Description, f => f.Commerce.ProductDescription())
|
||||
.Generate();
|
||||
varTable.IsActive = true;
|
||||
return varTable;
|
||||
}
|
||||
|
||||
public static Variable FakeVariable()
|
||||
{
|
||||
var dbVariable = new Faker<Variable>()
|
||||
.RuleFor(d => d.Name, f => f.Commerce.ProductName())
|
||||
.RuleFor(d => d.S7Address, f => $"DB1.DBD{f.Random.Int(0, 1000)}")
|
||||
.RuleFor(d => d.OpcUaNodeId, f => $"ns=2;s=My.DbDevice.Variable{f.Random.Int(1, 100)}")
|
||||
.RuleFor(d => d.ConversionFormula, f => "x * 1.0")
|
||||
.RuleFor(d => d.UpdatedBy, f => f.Name.FullName())
|
||||
.Generate();
|
||||
|
||||
// dbVariable.DataType = 1;
|
||||
// dbVariable.PollLevel = 1;
|
||||
dbVariable.IsActive = true;
|
||||
dbVariable.VariableTableId = 1;
|
||||
dbVariable.IsHistoryEnabled = true;
|
||||
dbVariable.HistoryDeadband = 0.1;
|
||||
dbVariable.IsAlarmEnabled = false;
|
||||
dbVariable.AlarmMinValue = 0;
|
||||
dbVariable.AlarmMaxValue = 100;
|
||||
dbVariable.AlarmDeadband = 1;
|
||||
dbVariable.Protocol = 0;
|
||||
dbVariable.CSharpDataType = 0;
|
||||
dbVariable.CreatedAt = DateTime.Now;
|
||||
dbVariable.UpdatedAt = DateTime.Now;
|
||||
dbVariable.IsModified = false;
|
||||
|
||||
return dbVariable;
|
||||
}
|
||||
|
||||
public static DbMenu FakeDbMenu()
|
||||
{
|
||||
var dbMenu = new Faker<DbMenu>()
|
||||
.RuleFor(d => d.Header, f => f.Commerce.Department())
|
||||
.RuleFor(d => d.Icon, f => f.Random.Word())
|
||||
.RuleFor(d => d.DisplayOrder, f => f.Random.Number(1, 10))
|
||||
.Generate();
|
||||
dbMenu.ParentId = 0;
|
||||
dbMenu.Childrens = new List<DbMenu>();
|
||||
return dbMenu;
|
||||
}
|
||||
|
||||
public static DbMqttServer FakeDbMqttServer()
|
||||
{
|
||||
var dbMqttServer = new Faker<DbMqttServer>()
|
||||
.RuleFor(d => d.ServerName, f => f.Company.CompanyName())
|
||||
.RuleFor(d => d.BrokerAddress, f => f.Internet.Ip())
|
||||
.RuleFor(d => d.Username, f => f.Internet.UserName())
|
||||
.RuleFor(d => d.Password, f => f.Internet.Password())
|
||||
.RuleFor(d => d.SubscribeTopic, f => "/topic/sub")
|
||||
.RuleFor(d => d.PublishTopic, f => "/topic/pub")
|
||||
.RuleFor(d => d.ClientId, f => Guid.NewGuid()
|
||||
.ToString())
|
||||
.RuleFor(d => d.MessageFormat, f => "JSON")
|
||||
.Generate();
|
||||
dbMqttServer.Port = 1883;
|
||||
dbMqttServer.IsActive = true;
|
||||
dbMqttServer.CreatedAt = DateTime.Now;
|
||||
return dbMqttServer;
|
||||
}
|
||||
|
||||
public static CreateDeviceDto FakeCreateDeviceDto()
|
||||
{
|
||||
var deviceDto = new Faker<CreateDeviceDto>()
|
||||
.RuleFor(d => d.Name, f => f.Commerce.ProductName())
|
||||
.RuleFor(d => d.Description, f => f.Commerce.ProductDescription())
|
||||
.RuleFor(d => d.IpAddress, f => f.Internet.Ip())
|
||||
.RuleFor(d => d.OpcUaServerUrl, f => f.Internet.Url())
|
||||
.Generate();
|
||||
deviceDto.Port = 102;
|
||||
deviceDto.Protocol = ProtocolType.S7;
|
||||
deviceDto.Slot = 1;
|
||||
deviceDto.Rack = 0;
|
||||
deviceDto.CpuType = "S7-1200";
|
||||
deviceDto.DeviceType = Core.Enums.DeviceType.SiemensPLC;
|
||||
|
||||
return deviceDto;
|
||||
}
|
||||
|
||||
public static MenuBeanDto FakeCreateMenuDto()
|
||||
{
|
||||
var menuDto = new Faker<MenuBeanDto>()
|
||||
.RuleFor(m => m.Header, f => f.Commerce.ProductName())
|
||||
.RuleFor(m => m.Icon, f => f.Random.Word())
|
||||
.RuleFor(m => m.DisplayOrder, f => f.Random.Number(1, 100))
|
||||
.RuleFor(m => m.ParentId, f => f.Random.Number(0, 10)) // 假设可以有父菜单
|
||||
.RuleFor(m => m.MenuType, f => f.PickRandom<MenuType>()) // 假设 MenuType 是一个枚举
|
||||
.Generate();
|
||||
return menuDto;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
64
DMS.Infrastructure.UnitTests/Services/BaseServiceTest.cs
Normal file
64
DMS.Infrastructure.UnitTests/Services/BaseServiceTest.cs
Normal file
@@ -0,0 +1,64 @@
|
||||
// DMS.Infrastructure.UnitTests/Services/BaseServiceTest.cs
|
||||
|
||||
using AutoMapper;
|
||||
using AutoMapper.Internal;
|
||||
using DMS.Application.Interfaces;
|
||||
using DMS.Application.Services;
|
||||
using DMS.Core.Interfaces;
|
||||
using DMS.Core.Interfaces.Repositories;
|
||||
using DMS.Infrastructure.Data;
|
||||
using DMS.Infrastructure.Repositories;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using DMS.Infrastructure.Configurations;
|
||||
|
||||
|
||||
namespace DMS.Infrastructure.UnitTests.Services;
|
||||
|
||||
public class BaseServiceTest
|
||||
{
|
||||
// ServiceProvider 将是所有测试的服务容器
|
||||
protected readonly IServiceProvider ServiceProvider;
|
||||
|
||||
public BaseServiceTest()
|
||||
{
|
||||
var services = new ServiceCollection();
|
||||
|
||||
// --- 核心配置 ---
|
||||
services.AddAutoMapper(cfg =>
|
||||
{
|
||||
// 最终解决方案:根据异常信息的建议,设置此标记以忽略重复的Profile加载。
|
||||
// 注意:此属性位于 Internal() 方法下。
|
||||
cfg.Internal().AllowAdditiveTypeMapCreation = true;
|
||||
|
||||
cfg.AddProfile(new DMS.Application.Profiles.MappingProfile());
|
||||
cfg.AddProfile(new DMS.Infrastructure.Profiles.MappingProfile());
|
||||
});
|
||||
|
||||
// 2. 配置数据库上下文 (在测试中通常使用单例)
|
||||
services.AddSingleton<SqlSugarDbContext>(_ =>
|
||||
{
|
||||
var appSettings = new AppSettings { Database = { Database = "dms_test" } };
|
||||
return new SqlSugarDbContext(appSettings);
|
||||
});
|
||||
|
||||
// --- 注册服务和仓储 ---
|
||||
// 使用 Transient 或 Scoped 取决于服务的生命周期需求,对于测试,Transient 通常更安全。
|
||||
|
||||
// 注册仓储管理器
|
||||
services.AddTransient<IRepositoryManager, RepositoryManager>();
|
||||
services.AddTransient<IInitializeRepository, InitializeRepository>();
|
||||
|
||||
// 注册应用服务
|
||||
services.AddTransient<IDeviceAppService, DeviceService>();
|
||||
// services.AddTransient<IVariableAppService, VariableAppService>(); // 如果需要测试 VariableService,取消此行注释
|
||||
// ... 在这里注册所有其他的应用服务 ...
|
||||
|
||||
|
||||
// --- 构建服务提供程序 ---
|
||||
ServiceProvider = services.BuildServiceProvider();
|
||||
|
||||
// 验证 AutoMapper 配置 (可选,但强烈推荐)
|
||||
var mapper = ServiceProvider.GetService<IMapper>();
|
||||
mapper?.ConfigurationProvider.AssertConfigurationIsValid();
|
||||
}
|
||||
}
|
||||
@@ -1,31 +0,0 @@
|
||||
using DMS.Core.Interfaces;
|
||||
using DMS.Infrastructure.Configurations;
|
||||
using DMS.Infrastructure.Data;
|
||||
using DMS.Infrastructure.Services;
|
||||
|
||||
namespace DMS.Infrastructure.UnitTests.Services;
|
||||
|
||||
public class DatabaseServiceTest
|
||||
{
|
||||
|
||||
private IDatabaseService _databaseService;
|
||||
public DatabaseServiceTest()
|
||||
{
|
||||
AppSettings appSettings = new AppSettings();
|
||||
appSettings.Database.Database = "dms_test";
|
||||
SqlSugarDbContext dbContext=new SqlSugarDbContext(appSettings);
|
||||
_databaseService = new DatabaseService(dbContext);
|
||||
}
|
||||
[Fact]
|
||||
public void InitializeTables_Test()
|
||||
{
|
||||
_databaseService.InitializeTables();
|
||||
Assert.True(_databaseService.IsAnyTable("dbdevice"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InitializeTableIndex_Test()
|
||||
{
|
||||
_databaseService.InitializeTableIndex();
|
||||
}
|
||||
}
|
||||
@@ -1,73 +1,41 @@
|
||||
using AutoMapper;
|
||||
using DMS.Core.Models;
|
||||
using DMS.Infrastructure.Configurations;
|
||||
using DMS.Infrastructure.Data;
|
||||
using DMS.Infrastructure.Profiles;
|
||||
using DMS.Infrastructure.Repositories;
|
||||
using DMS.Infrastructure.Services;
|
||||
using DMS.Application.DTOs;
|
||||
using DMS.Application.Interfaces;
|
||||
using DMS.Application.Services;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace DMS.Infrastructure.UnitTests.Services;
|
||||
|
||||
[TestSubject(typeof(DeviceService))]
|
||||
public class DeviceServiceTest
|
||||
public class DeviceServiceTest : BaseServiceTest // 继承基类
|
||||
{
|
||||
private readonly DeviceRepository _deviceRepository;
|
||||
private readonly DeviceService _deviceService;
|
||||
private readonly IMapper _mapper;
|
||||
private readonly IDeviceAppService _deviceService;
|
||||
|
||||
public DeviceServiceTest()
|
||||
public DeviceServiceTest() : base()
|
||||
{
|
||||
// 1. 创建 MapperConfiguration
|
||||
var mappingConfig = new MapperConfiguration(mc =>
|
||||
// 从 IoC 容器中解析出需要测试的服务
|
||||
// 使用 GetRequiredService 可以确保如果服务未注册,测试会立即失败,这通常是我们想要的。
|
||||
_deviceService = ServiceProvider.GetRequiredService<IDeviceAppService>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task CreateDeviceWithDetailsAsyncTest()
|
||||
{
|
||||
// Arrange
|
||||
var dto = new CreateDeviceWithDetailsDto
|
||||
{
|
||||
// 添加你的所有 Profile
|
||||
mc.AddProfile(new MappingProfile());
|
||||
// 如果有其他 Profile,也可以在这里添加
|
||||
// mc.AddProfile(new AnotherProfile());
|
||||
});
|
||||
Device = FakerHelper.FakeCreateDeviceDto(),
|
||||
VariableTable = FakerHelper.FakeVariableTableDto(),
|
||||
DeviceMenu = FakerHelper.FakeCreateMenuDto(),
|
||||
VariableTableMenu = FakerHelper.FakeCreateMenuDto()
|
||||
|
||||
// ... 填充其他需要的数据
|
||||
};
|
||||
|
||||
// 2. 验证映射配置是否有效 (可选,但在开发环境中推荐)
|
||||
mappingConfig.AssertConfigurationIsValid();
|
||||
// 3. 创建 IMapper 实例
|
||||
_mapper = mappingConfig.CreateMapper();
|
||||
// Act
|
||||
var addedDeviceId = await _deviceService.CreateDeviceWithDetailsAsync(dto);
|
||||
|
||||
|
||||
AppSettings appSettings = new AppSettings();
|
||||
appSettings.Database.Database = "dms_test";
|
||||
SqlSugarDbContext dbContext = new SqlSugarDbContext(appSettings);
|
||||
_deviceRepository= new DeviceRepository(_mapper,dbContext);
|
||||
_deviceService = new DeviceService(_deviceRepository);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddAsync_Test()
|
||||
{
|
||||
var dbDevice = FakerHelper.FakeDbDevice();
|
||||
var addDevice= await _deviceService.AddAsync(_mapper.Map<Device>(dbDevice));
|
||||
Assert.NotEqual(0, addDevice.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TakeAsync_Test()
|
||||
{
|
||||
var device= await _deviceService.TakeAsync(2);
|
||||
Assert.Equal(2,device.Count);
|
||||
}
|
||||
[Fact]
|
||||
public async Task UpdateAsync_Test()
|
||||
{
|
||||
var devices= await _deviceService.TakeAsync(1);
|
||||
devices[0].IpAddress = "127.0.0.1";
|
||||
var res= await _deviceService.UpdateAsync(devices[0]);
|
||||
Assert.Equal(1,res);
|
||||
}
|
||||
[Fact]
|
||||
public async Task DeleteAsync_Test()
|
||||
{
|
||||
var devices= await _deviceService.TakeAsync(1);
|
||||
var res= await _deviceService.DeleteAsync(devices[0]);
|
||||
Assert.Equal(1,res);
|
||||
// Assert
|
||||
Assert.NotEqual(0, addedDeviceId);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
using DMS.Application.Interfaces;
|
||||
using DMS.Application.Services;
|
||||
using DMS.Core.Interfaces.Repositories;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
|
||||
namespace DMS.Infrastructure.UnitTests.Services;
|
||||
|
||||
[TestSubject(typeof(InitializeService))]
|
||||
public class InitializeServiceTest:BaseServiceTest
|
||||
{
|
||||
private readonly IInitializeRepository _initializeRepository;
|
||||
|
||||
public InitializeServiceTest()
|
||||
{
|
||||
_initializeRepository = ServiceProvider.GetRequiredService<IInitializeRepository>();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InitializeTablesTest()
|
||||
{
|
||||
_initializeRepository.InitializeTables();
|
||||
}
|
||||
}
|
||||
@@ -1,71 +0,0 @@
|
||||
using AutoMapper;
|
||||
using DMS.Core.Models;
|
||||
using DMS.Infrastructure.Configurations;
|
||||
using DMS.Infrastructure.Data;
|
||||
using DMS.Infrastructure.Profiles;
|
||||
using DMS.Infrastructure.Repositories;
|
||||
using DMS.Infrastructure.Services;
|
||||
|
||||
namespace DMS.Infrastructure.UnitTests.Services;
|
||||
|
||||
public class VariableTableServieTest
|
||||
{
|
||||
private readonly VariableTableRepository _variableTableRepository;
|
||||
private readonly VariableTableService _variableTableService;
|
||||
private readonly IMapper _mapper;
|
||||
|
||||
public VariableTableServieTest()
|
||||
{
|
||||
// 1. 创建 MapperConfiguration
|
||||
var mappingConfig = new MapperConfiguration(mc =>
|
||||
|
||||
{
|
||||
// 添加你的所有 Profile
|
||||
mc.AddProfile(new MappingProfile());
|
||||
// 如果有其他 Profile,也可以在这里添加
|
||||
// mc.AddProfile(new AnotherProfile());
|
||||
});
|
||||
|
||||
// 2. 验证映射配置是否有效 (可选,但在开发环境中推荐)
|
||||
mappingConfig.AssertConfigurationIsValid();
|
||||
// 3. 创建 IMapper 实例
|
||||
_mapper = mappingConfig.CreateMapper();
|
||||
|
||||
|
||||
AppSettings appSettings = new AppSettings();
|
||||
appSettings.Database.Database = "dms_test";
|
||||
SqlSugarDbContext dbContext = new SqlSugarDbContext(appSettings);
|
||||
_variableTableRepository= new VariableTableRepository(_mapper,dbContext);
|
||||
_variableTableService = new VariableTableService(_variableTableRepository);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AddAsync_Test()
|
||||
{
|
||||
// var dbDevice = FakerHelper
|
||||
// var addDevice= await _variableTableService.AddAsync(_mapper.Map<Device>(dbDevice));
|
||||
// Assert.NotEqual(0, addDevice.Id);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task TakeAsync_Test()
|
||||
{
|
||||
var device= await _variableTableService.TakeAsync(2);
|
||||
Assert.Equal(2,device.Count);
|
||||
}
|
||||
[Fact]
|
||||
public async Task UpdateAsync_Test()
|
||||
{
|
||||
var devices= await _variableTableService.TakeAsync(1);
|
||||
// devices[0].IpAddress = "127.0.0.1";
|
||||
var res= await _variableTableService.UpdateAsync(devices[0]);
|
||||
Assert.Equal(1,res);
|
||||
}
|
||||
[Fact]
|
||||
public async Task DeleteAsync_Test()
|
||||
{
|
||||
var devices= await _variableTableService.TakeAsync(1);
|
||||
var res= await _variableTableService.DeleteAsync(devices[0]);
|
||||
Assert.Equal(1,res);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user