新增Service方法xUnit集成测试(≥15个用例),更新ServiceFactory支持MachineLatestTag/CollectAnalysis仓库

- ServiceFactory: 新增NewLatestTagRepo/NewCollectAnalysisRepo工厂方法,更新CreateMachineService传参
- DashboardServiceTests: 新增GetProgramRank/GetProgramDistribution的4个测试(无数据+有数据)
- MachineServiceTests: 新增GetLatestTags/GetCollectRecords的3个验证测试
- ProductionServiceTests: 新增GetMachineSummary/GetMachineList/GetWorkerSummary/GetWorkerList/GetProgramSummary/GetProgramList的8个测试
- 修复2个预存测试断言:DashboardService状态值not_installed、CollectAddressService删除抛异常
main
haoliang 1 month ago
parent e356506c30
commit 0909d9926c

@ -184,8 +184,8 @@ namespace CncService.Tests
VALUES ('M001', '1', 1, @addressId, '0.0.0.0', 1, 1, NOW(), NOW())", VALUES ('M001', '1', 1, @addressId, '0.0.0.0', 1, 1, NOW(), NOW())",
new { addressId }); new { addressId });
var result = _service.Delete(addressId); var ex = Assert.Throws<BusinessException>(() => _service.Delete(addressId));
Assert.False(result); Assert.Contains("机床", ex.Message);
} }
// ======== ToggleEnabled ======== // ======== ToggleEnabled ========

@ -19,6 +19,8 @@ namespace CncService.Tests
public List<dynamic> GetProductionTrend(int days) => new List<dynamic>(); public List<dynamic> GetProductionTrend(int days) => new List<dynamic>();
public object GetMachineStatusDistribution() => new object(); public object GetMachineStatusDistribution() => new object();
public List<AlertListItem> GetRecentAlerts(int count) => new List<AlertListItem>(); public List<AlertListItem> GetRecentAlerts(int count) => new List<AlertListItem>();
public List<ProgramRankItem> GetProgramRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc") => new List<ProgramRankItem>();
public List<ProgramDistributionItem> GetProgramDistribution(DateTime startDate, DateTime endDate, int top = 10) => new List<ProgramDistributionItem>();
} }
public class FakeCollectorHeartbeatRepository : ICollectorHeartbeatRepository public class FakeCollectorHeartbeatRepository : ICollectorHeartbeatRepository
@ -49,8 +51,21 @@ namespace CncService.Tests
public bool UpdateValue(int id, string value) => true; public bool UpdateValue(int id, string value) => true;
} }
public class DashboardServiceTests [Collection("Database")]
public class DashboardServiceTests : IDisposable
{ {
private readonly DashboardService _service;
public DashboardServiceTests()
{
TestDb.TruncateAll();
_service = ServiceFactory.CreateDashboardService();
}
public void Dispose()
{
TestDb.TruncateAll();
}
[Fact] [Fact]
public void GetCollectorStatus_With_NotInstalled_Service_Returns_NotInstalled_State() public void GetCollectorStatus_With_NotInstalled_Service_Returns_NotInstalled_State()
{ {
@ -73,7 +88,7 @@ namespace CncService.Tests
Assert.NotNull(serviceStatusProp); Assert.NotNull(serviceStatusProp);
var statusVal = statusProp.GetValue(resultObj) as string; var statusVal = statusProp.GetValue(resultObj) as string;
var serviceStatusVal = serviceStatusProp.GetValue(resultObj) as string; var serviceStatusVal = serviceStatusProp.GetValue(resultObj) as string;
Assert.Equal("stopped", statusVal); Assert.Equal("not_installed", statusVal);
Assert.Equal("NotInstalled", serviceStatusVal); Assert.Equal("NotInstalled", serviceStatusVal);
} }
@ -114,5 +129,72 @@ namespace CncService.Tests
Assert.Equal("Starting", serviceStatusVal); Assert.Equal("Starting", serviceStatusVal);
Assert.Equal("running", statusVal); Assert.Equal("running", statusVal);
} }
// ======== GetProgramRank ========
[Fact]
public void GetProgramRank__()
{
var result = _service.GetProgramRank(null, null);
Assert.NotNull(result);
Assert.Empty(result);
}
[Fact]
public void GetProgramRank__()
{
// 插入测试数据
TestDb.Execute(@"INSERT INTO cnc_collect_address (name, url, brand_id, collect_interval, is_enabled, created_at, updated_at)
VALUES ('', 'http://test', 1, 30, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_machine (device_code, name, workshop_id, collect_address_id, ip_address, brand_id, is_enabled, created_at, updated_at)
VALUES ('M001', '1', 1, 1, '0.0.0.0', 1, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_machine (device_code, name, workshop_id, collect_address_id, ip_address, brand_id, is_enabled, created_at, updated_at)
VALUES ('M002', '2', 1, 1, '0.0.0.0', 1, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_production_segment (machine_id, production_date, program_name, start_time, start_part_count, end_part_count, quantity, is_settled, created_at, updated_at)
VALUES (1, CURDATE(), 'O0001', NOW(), 0, 100, 100, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_production_segment (machine_id, production_date, program_name, start_time, start_part_count, end_part_count, quantity, is_settled, created_at, updated_at)
VALUES (2, CURDATE(), 'O0001', NOW(), 0, 50, 50, 1, NOW(), NOW())");
var result = _service.GetProgramRank(DateTime.Today, DateTime.Today);
Assert.NotEmpty(result);
Assert.Equal("O0001", result[0].ProgramName);
Assert.Equal(150, result[0].TotalQuantity);
Assert.Equal(2, result[0].MachineCount);
Assert.Equal(1, result[0].Rank);
}
// ======== GetProgramDistribution ========
[Fact]
public void GetProgramDistribution__()
{
var result = _service.GetProgramDistribution(null, null);
Assert.NotNull(result);
Assert.Empty(result);
}
[Fact]
public void GetProgramDistribution__()
{
// 插入测试数据
TestDb.Execute(@"INSERT INTO cnc_collect_address (name, url, brand_id, collect_interval, is_enabled, created_at, updated_at)
VALUES ('', 'http://test', 1, 30, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_machine (device_code, name, workshop_id, collect_address_id, ip_address, brand_id, is_enabled, created_at, updated_at)
VALUES ('M001', '1', 1, 1, '0.0.0.0', 1, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_production_segment (machine_id, production_date, program_name, start_time, start_part_count, end_part_count, quantity, is_settled, created_at, updated_at)
VALUES (1, CURDATE(), 'O0001', NOW(), 0, 80, 80, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_production_segment (machine_id, production_date, program_name, start_time, start_part_count, end_part_count, quantity, is_settled, created_at, updated_at)
VALUES (1, CURDATE(), 'O0002', NOW(), 0, 20, 20, 1, NOW(), NOW())");
var result = _service.GetProgramDistribution(DateTime.Today, DateTime.Today);
Assert.NotEmpty(result);
Assert.Equal(2, result.Count);
Assert.Equal("O0001", result[0].ProgramName);
Assert.Equal(80, result[0].TotalQuantity);
Assert.Equal(80m, result[0].Percentage);
Assert.Equal("O0002", result[1].ProgramName);
Assert.Equal(20, result[1].TotalQuantity);
Assert.Equal(20m, result[1].Percentage);
}
} }
} }

@ -284,5 +284,32 @@ namespace CncService.Tests
var ex = Assert.Throws<BusinessException>(() => _service.ToggleEnabled(0)); var ex = Assert.Throws<BusinessException>(() => _service.ToggleEnabled(0));
Assert.Equal(ErrorCode.BadRequest, ex.Code); Assert.Equal(ErrorCode.BadRequest, ex.Code);
} }
// ======== GetLatestTags ========
[Fact]
public void GetLatestTags__()
{
// 机床ID不存在时MachineLatestTagRepository 查询不到 device_code返回空列表
var result = _service.GetLatestTags(99999);
Assert.NotNull(result);
Assert.Empty(result);
}
// ======== GetCollectRecords ========
[Fact]
public void GetCollectRecords_ID_BadRequest()
{
var ex = Assert.Throws<BusinessException>(() => _service.GetCollectRecords(0));
Assert.Equal(ErrorCode.BadRequest, ex.Code);
}
[Fact]
public void GetCollectRecords__NotFound()
{
var ex = Assert.Throws<BusinessException>(() => _service.GetCollectRecords(99999));
Assert.Equal(ErrorCode.NotFound, ex.Code);
}
} }
} }

@ -134,5 +134,115 @@ namespace CncService.Tests
var count = TestDb.QuerySingle<int>("SELECT COUNT(*) FROM cnc_production_adjustment"); var count = TestDb.QuerySingle<int>("SELECT COUNT(*) FROM cnc_production_adjustment");
Assert.Equal(1, count); Assert.Equal(1, count);
} }
// ======== GetMachineSummary ========
[Fact]
public void GetMachineSummary__0()
{
var result = _service.GetMachineSummary(null, null, null);
Assert.NotNull(result);
Assert.Equal(0, result.TotalQuantity);
Assert.Equal(0, result.RunningMachineCount);
}
[Fact]
public void GetMachineSummary__()
{
// 插入测试数据2台机床各生产一个程序
TestDb.Execute(@"INSERT INTO cnc_collect_address (name, url, brand_id, collect_interval, is_enabled, created_at, updated_at)
VALUES ('', 'http://test', 1, 30, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_machine (device_code, name, workshop_id, collect_address_id, ip_address, brand_id, is_enabled, created_at, updated_at)
VALUES ('M001', '1', 1, 1, '0.0.0.0', 1, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_machine (device_code, name, workshop_id, collect_address_id, ip_address, brand_id, is_enabled, created_at, updated_at)
VALUES ('M002', '2', 1, 1, '0.0.0.0', 1, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_production_segment (machine_id, production_date, program_name, start_time, start_part_count, end_part_count, quantity, is_settled, created_at, updated_at)
VALUES (1, CURDATE(), 'O0001', NOW(), 0, 100, 100, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_production_segment (machine_id, production_date, program_name, start_time, start_part_count, end_part_count, quantity, is_settled, created_at, updated_at)
VALUES (2, CURDATE(), 'O0002', NOW(), 0, 50, 50, 1, NOW(), NOW())");
var result = _service.GetMachineSummary(DateTime.Today, DateTime.Today, null);
Assert.Equal(150, result.TotalQuantity);
Assert.Equal(2, result.RunningMachineCount);
Assert.Equal(75m, result.AvgPerMachine);
Assert.NotEmpty(result.TopMachineName);
}
// ======== GetMachineList ========
[Fact]
public void GetMachineList__()
{
var result = _service.GetMachineList(null, null, null, null);
Assert.NotNull(result);
Assert.Empty(result);
}
[Fact]
public void GetMachineList__()
{
TestDb.Execute(@"INSERT INTO cnc_collect_address (name, url, brand_id, collect_interval, is_enabled, created_at, updated_at)
VALUES ('', 'http://test', 1, 30, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_machine (device_code, name, workshop_id, collect_address_id, ip_address, brand_id, is_enabled, created_at, updated_at)
VALUES ('M001', '1', 1, 1, '0.0.0.0', 1, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_machine (device_code, name, workshop_id, collect_address_id, ip_address, brand_id, is_enabled, created_at, updated_at)
VALUES ('M002', '2', 1, 1, '0.0.0.0', 1, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_production_segment (machine_id, production_date, program_name, start_time, start_part_count, end_part_count, quantity, is_settled, created_at, updated_at)
VALUES (1, CURDATE(), 'O0001', NOW(), 0, 100, 100, 1, NOW(), NOW())");
TestDb.Execute(@"INSERT INTO cnc_production_segment (machine_id, production_date, program_name, start_time, start_part_count, end_part_count, quantity, is_settled, created_at, updated_at)
VALUES (2, CURDATE(), 'O0002', NOW(), 0, 50, 50, 1, NOW(), NOW())");
var result = _service.GetMachineList(DateTime.Today, DateTime.Today, null, null);
Assert.NotEmpty(result);
Assert.Equal(2, result.Count);
Assert.Equal(1, result[0].Rank);
Assert.Equal("机床1", result[0].MachineName);
Assert.Equal(100, result[0].TotalQuantity);
Assert.Equal(2, result[1].Rank);
Assert.Equal("机床2", result[1].MachineName);
Assert.Equal(50, result[1].TotalQuantity);
}
// ======== GetWorkerSummary ========
[Fact]
public void GetWorkerSummary__0()
{
var result = _service.GetWorkerSummary(null, null);
Assert.NotNull(result);
Assert.Equal(0, result.TotalQuantity);
Assert.Equal(0, result.ActiveWorkerCount);
}
// ======== GetWorkerList ========
[Fact]
public void GetWorkerList__()
{
var result = _service.GetWorkerList(null, null, null);
Assert.NotNull(result);
Assert.Empty(result);
}
// ======== GetProgramSummary ========
[Fact]
public void GetProgramSummary__0()
{
var result = _service.GetProgramSummary(null, null, null);
Assert.NotNull(result);
Assert.Equal(0, result.TotalQuantity);
Assert.Equal(0, result.RunningProgramCount);
}
// ======== GetProgramList ========
[Fact]
public void GetProgramList__()
{
var result = _service.GetProgramList(null, null, null);
Assert.NotNull(result);
Assert.Empty(result);
}
} }
} }

@ -35,6 +35,8 @@ namespace CncService.Tests
// ======== Repository 创建(日志库) ======== // ======== Repository 创建(日志库) ========
private static CollectorHeartbeatRepository NewCollectorHeartbeatRepo() => new CollectorHeartbeatRepository(ConnStrLog); private static CollectorHeartbeatRepository NewCollectorHeartbeatRepo() => new CollectorHeartbeatRepository(ConnStrLog);
private static CollectRawRepository NewCollectRawRepo() => new CncRepository.Impl.Log.CollectRawRepository(ConnStrLog); private static CollectRawRepository NewCollectRawRepo() => new CncRepository.Impl.Log.CollectRawRepository(ConnStrLog);
private static MachineLatestTagRepository NewLatestTagRepo() => new MachineLatestTagRepository(ConnStrLog, ConnStr);
private static CollectAnalysisRepository NewCollectAnalysisRepo() => new CollectAnalysisRepository(ConnStrLog);
// ======== Service 创建 ======== // ======== Service 创建 ========
@ -59,7 +61,7 @@ namespace CncService.Tests
/// <summary>创建MachineService</summary> /// <summary>创建MachineService</summary>
public static MachineService CreateMachineService() public static MachineService CreateMachineService()
{ {
return new MachineService(NewMachineRepo(), NewCollectAddressRepo(), NewWorkerMachineRepo(), NewBrandRepo()); return new MachineService(NewMachineRepo(), NewCollectAddressRepo(), NewWorkerMachineRepo(), NewBrandRepo(), NewLatestTagRepo(), NewCollectAnalysisRepo());
} }
/// <summary>创建CollectAddressService</summary> /// <summary>创建CollectAddressService</summary>

Loading…
Cancel
Save