From 0909d9926c4e9cd71e7ceaafac49a0cfc5c39c27 Mon Sep 17 00:00:00 2001 From: haoliang <821644@qq.com> Date: Wed, 13 May 2026 13:39:05 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9EService=E6=96=B9=E6=B3=95xUni?= =?UTF-8?q?t=E9=9B=86=E6=88=90=E6=B5=8B=E8=AF=95=EF=BC=88=E2=89=A515?= =?UTF-8?q?=E4=B8=AA=E7=94=A8=E4=BE=8B=EF=BC=89=EF=BC=8C=E6=9B=B4=E6=96=B0?= =?UTF-8?q?ServiceFactory=E6=94=AF=E6=8C=81MachineLatestTag/CollectAnalysi?= =?UTF-8?q?s=E4=BB=93=E5=BA=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 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删除抛异常 --- .../CollectAddressServiceTests.cs | 4 +- .../CncService.Tests/DashboardServiceTests.cs | 86 +++++++++++++- tests/CncService.Tests/MachineServiceTests.cs | 27 +++++ .../ProductionServiceTests.cs | 110 ++++++++++++++++++ tests/CncService.Tests/ServiceFactory.cs | 4 +- 5 files changed, 226 insertions(+), 5 deletions(-) diff --git a/tests/CncService.Tests/CollectAddressServiceTests.cs b/tests/CncService.Tests/CollectAddressServiceTests.cs index d50dbc9..af2038c 100644 --- a/tests/CncService.Tests/CollectAddressServiceTests.cs +++ b/tests/CncService.Tests/CollectAddressServiceTests.cs @@ -184,8 +184,8 @@ namespace CncService.Tests VALUES ('M001', '机床1', 1, @addressId, '0.0.0.0', 1, 1, NOW(), NOW())", new { addressId }); - var result = _service.Delete(addressId); - Assert.False(result); + var ex = Assert.Throws(() => _service.Delete(addressId)); + Assert.Contains("机床", ex.Message); } // ======== ToggleEnabled ======== diff --git a/tests/CncService.Tests/DashboardServiceTests.cs b/tests/CncService.Tests/DashboardServiceTests.cs index cba34a9..9e152e1 100644 --- a/tests/CncService.Tests/DashboardServiceTests.cs +++ b/tests/CncService.Tests/DashboardServiceTests.cs @@ -19,6 +19,8 @@ namespace CncService.Tests public List GetProductionTrend(int days) => new List(); public object GetMachineStatusDistribution() => new object(); public List GetRecentAlerts(int count) => new List(); + public List GetProgramRank(DateTime startDate, DateTime endDate, int top, string sortOrder = "desc") => new List(); + public List GetProgramDistribution(DateTime startDate, DateTime endDate, int top = 10) => new List(); } public class FakeCollectorHeartbeatRepository : ICollectorHeartbeatRepository @@ -49,8 +51,21 @@ namespace CncService.Tests 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] public void GetCollectorStatus_With_NotInstalled_Service_Returns_NotInstalled_State() { @@ -73,7 +88,7 @@ namespace CncService.Tests Assert.NotNull(serviceStatusProp); var statusVal = statusProp.GetValue(resultObj) as string; var serviceStatusVal = serviceStatusProp.GetValue(resultObj) as string; - Assert.Equal("stopped", statusVal); + Assert.Equal("not_installed", statusVal); Assert.Equal("NotInstalled", serviceStatusVal); } @@ -114,5 +129,72 @@ namespace CncService.Tests Assert.Equal("Starting", serviceStatusVal); 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); + } } } diff --git a/tests/CncService.Tests/MachineServiceTests.cs b/tests/CncService.Tests/MachineServiceTests.cs index 30ec331..6a62c99 100644 --- a/tests/CncService.Tests/MachineServiceTests.cs +++ b/tests/CncService.Tests/MachineServiceTests.cs @@ -284,5 +284,32 @@ namespace CncService.Tests var ex = Assert.Throws(() => _service.ToggleEnabled(0)); 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(() => _service.GetCollectRecords(0)); + Assert.Equal(ErrorCode.BadRequest, ex.Code); + } + + [Fact] + public void GetCollectRecords_机床不存在_抛出NotFound异常() + { + var ex = Assert.Throws(() => _service.GetCollectRecords(99999)); + Assert.Equal(ErrorCode.NotFound, ex.Code); + } } } diff --git a/tests/CncService.Tests/ProductionServiceTests.cs b/tests/CncService.Tests/ProductionServiceTests.cs index fae2557..9cbc80f 100644 --- a/tests/CncService.Tests/ProductionServiceTests.cs +++ b/tests/CncService.Tests/ProductionServiceTests.cs @@ -134,5 +134,115 @@ namespace CncService.Tests var count = TestDb.QuerySingle("SELECT COUNT(*) FROM cnc_production_adjustment"); 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); + } } } diff --git a/tests/CncService.Tests/ServiceFactory.cs b/tests/CncService.Tests/ServiceFactory.cs index 1f04b5a..b272001 100644 --- a/tests/CncService.Tests/ServiceFactory.cs +++ b/tests/CncService.Tests/ServiceFactory.cs @@ -35,6 +35,8 @@ namespace CncService.Tests // ======== Repository 创建(日志库) ======== private static CollectorHeartbeatRepository NewCollectorHeartbeatRepo() => new CollectorHeartbeatRepository(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 创建 ======== @@ -59,7 +61,7 @@ namespace CncService.Tests /// 创建MachineService public static MachineService CreateMachineService() { - return new MachineService(NewMachineRepo(), NewCollectAddressRepo(), NewWorkerMachineRepo(), NewBrandRepo()); + return new MachineService(NewMachineRepo(), NewCollectAddressRepo(), NewWorkerMachineRepo(), NewBrandRepo(), NewLatestTagRepo(), NewCollectAnalysisRepo()); } /// 创建CollectAddressService