using System; using System.Linq; using CncModels.Constants; using CncModels.Dto.Brand; using CncService; using CncService.Impl; using Xunit; namespace CncService.Tests { /// /// BrandService 品牌模板测试 /// 测试场景:CRUD、复制、删除约束(关联采集地址)、字段映射、标准字段 /// [Collection("Database")] public class BrandServiceTests : IDisposable { private readonly BrandService _service; public BrandServiceTests() { TestDb.TruncateAll(); _service = ServiceFactory.CreateBrandService(); } public void Dispose() { TestDb.TruncateAll(); } // ======== GetList ======== [Fact] public void GetList_返回种子数据品牌() { var list = _service.GetList(); Assert.NotNull(list); Assert.True(list.Count >= 1, "种子数据至少有1个品牌"); Assert.Contains(list, b => b.BrandName == "FANUC"); } [Fact] public void GetList_品牌列表包含FieldCount() { // FANUC种子数据默认无字段映射 var list = _service.GetList(); var fanuc = list.FirstOrDefault(b => b.BrandName == "FANUC"); Assert.NotNull(fanuc); Assert.Equal(0, fanuc.FieldCount); } // ======== GetById ======== [Fact] public void GetById_存在的ID_返回品牌详情() { var detail = _service.GetById(1); Assert.NotNull(detail); Assert.Equal("FANUC", detail.BrandName); Assert.Equal("device", detail.DeviceField); Assert.Equal("tags", detail.TagsPath); } [Fact] public void GetById_不存在的ID_抛出NotFound异常() { var ex = Assert.Throws(() => _service.GetById(99999)); Assert.Equal(ErrorCode.NotFound, ex.Code); } // ======== Create ======== [Fact] public void Create_正常新增_返回自增ID() { var id = _service.Create(new CreateBrandRequest { BrandName = "西门子", DeviceField = "siemens_device", TagsPath = "siemens_tags" }); Assert.True(id > 0); var created = _service.GetById(id); Assert.Equal("西门子", created.BrandName); Assert.Equal(1, created.IsEnabled); // 默认启用 } [Fact] public void Create_请求为null_抛出BadRequest异常() { var ex = Assert.Throws(() => _service.Create(null)); Assert.Equal(ErrorCode.BadRequest, ex.Code); } [Fact] public void Create_重复品牌名_抛出Conflict异常() { var ex = Assert.Throws(() => _service.Create(new CreateBrandRequest { BrandName = "FANUC", DeviceField = "device", TagsPath = "tags" })); Assert.Equal(ErrorCode.Conflict, ex.Code); } [Fact] public void Create_重复品牌名大小写不同_抛出Conflict异常() { var ex = Assert.Throws(() => _service.Create(new CreateBrandRequest { BrandName = "fanuc", DeviceField = "device", TagsPath = "tags" })); Assert.Equal(ErrorCode.Conflict, ex.Code); } // ======== Update ======== [Fact] public void Update_正常修改_返回true() { var result = _service.Update(1, new UpdateBrandRequest { BrandName = "FANUC-修改", DeviceField = "new_device", TagsPath = "new_tags" }); Assert.True(result); var updated = _service.GetById(1); Assert.Equal("FANUC-修改", updated.BrandName); } [Fact] public void Update_不存在的ID_抛出NotFound异常() { var ex = Assert.Throws(() => _service.Update(99999, new UpdateBrandRequest { BrandName = "不存在" })); Assert.Equal(ErrorCode.NotFound, ex.Code); } [Fact] public void Update_请求为null_抛出BadRequest异常() { var ex = Assert.Throws(() => _service.Update(1, null)); Assert.Equal(ErrorCode.BadRequest, ex.Code); } [Fact] public void Update_字段为null_保留原值() { var before = _service.GetById(1); _service.Update(1, new UpdateBrandRequest { BrandName = null, DeviceField = null, TagsPath = null }); var after = _service.GetById(1); Assert.Equal(before.BrandName, after.BrandName); Assert.Equal(before.DeviceField, after.DeviceField); Assert.Equal(before.TagsPath, after.TagsPath); } // ======== Delete ======== [Fact] public void Delete_无关联采集地址_返回true() { // 先新增一个品牌 var id = _service.Create(new CreateBrandRequest { BrandName = "待删除品牌", DeviceField = "del", TagsPath = "del" }); var result = _service.Delete(id); Assert.True(result); } [Fact] public void Delete_有关联采集地址_返回false() { // 新增采集地址关联到FANUC(brand_id=1) 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())"); var result = _service.Delete(1); Assert.False(result); } [Fact] public void Delete_不存在的ID_抛出NotFound异常() { var ex = Assert.Throws(() => _service.Delete(99999)); Assert.Equal(ErrorCode.NotFound, ex.Code); } // ======== ToggleEnabled ======== [Fact] public void ToggleEnabled_切换启用状态() { var before = _service.GetById(1); var beforeState = before.IsEnabled; _service.ToggleEnabled(1); var after = _service.GetById(1); Assert.NotEqual(beforeState, after.IsEnabled); } // ======== Copy ======== [Fact] public void Copy_正常复制_返回新品牌ID() { var newId = _service.Copy(1); Assert.True(newId > 0); Assert.NotEqual(1, newId); var copied = _service.GetById(newId); Assert.Equal("FANUC_Copy", copied.BrandName); Assert.Equal("device", copied.DeviceField); Assert.Equal("tags", copied.TagsPath); } [Fact] public void Copy_复制带字段映射的品牌() { // 给FANUC添加字段映射 TestDb.Execute(@"INSERT INTO cnc_brand_field_mapping (brand_id, standard_field, field_name, match_by, data_type, is_required, created_at) VALUES (1, 'Field1', 'field1_name', 'exact', 'string', 1, NOW()), (1, 'Field2', 'field2_name', 'exact', 'int', 0, NOW())"); var newId = _service.Copy(1); var copied = _service.GetById(newId); Assert.Equal(2, copied.FieldCount); } [Fact] public void Copy_不存在的ID_抛出NotFound异常() { var ex = Assert.Throws(() => _service.Copy(99999)); Assert.Equal(ErrorCode.NotFound, ex.Code); } // ======== GetStandardFields ======== [Fact] public void GetStandardFields_返回16个标准字段() { var fields = _service.GetStandardFields(); Assert.NotNull(fields); Assert.Equal(16, fields.Count); } [Fact] public void GetStandardFields_字段格式正确() { var fields = _service.GetStandardFields(); Assert.Equal("Field1", fields[0].StandardField); Assert.Equal("Field16", fields[15].StandardField); } } }