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.True(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);
}
// ======== FieldMapping IsEnabled ========
[Fact]
public void GetById_映射包含IsEnabled字段()
{
// 插入字段映射(含 is_enabled=0 的)
TestDb.Execute(@"INSERT INTO cnc_brand_field_mapping (brand_id, standard_field, field_name, match_by, data_type, is_required, is_enabled, created_at)
VALUES (1, 'program_name', 'Tag5', 'id', 'string', 1, 1, NOW()),
(1, 'spindle_load', 'Tag21', 'id', 'number', 0, 0, NOW())");
var detail = _service.GetById(1);
Assert.NotNull(detail.Mappings);
Assert.Equal(2, detail.Mappings.Count);
var disabled = detail.Mappings.FirstOrDefault(m => m.StandardField == "spindle_load");
Assert.NotNull(disabled);
Assert.Equal(0, disabled.IsEnabled);
}
[Fact]
public void Copy_复制品牌保留映射启用状态()
{
// 插入字段映射(1启用1禁用)
TestDb.Execute(@"INSERT INTO cnc_brand_field_mapping (brand_id, standard_field, field_name, match_by, data_type, is_required, is_enabled, created_at)
VALUES (1, 'program_name', 'Tag5', 'id', 'string', 1, 1, NOW()),
(1, 'spindle_load', 'Tag21', 'id', 'number', 0, 0, NOW())");
var newId = _service.Copy(1);
var copied = _service.GetById(newId);
Assert.Equal(2, copied.Mappings.Count);
var enabledMapping = copied.Mappings.First(m => m.StandardField == "program_name");
var disabledMapping = copied.Mappings.First(m => m.StandardField == "spindle_load");
Assert.Equal(1, enabledMapping.IsEnabled);
Assert.Equal(0, disabledMapping.IsEnabled);
}
[Fact]
public void GetById_映射列表区分启用禁用()
{
TestDb.Execute(@"INSERT INTO cnc_brand_field_mapping (brand_id, standard_field, field_name, match_by, data_type, is_required, is_enabled, created_at)
VALUES (1, 'f1', 'Tag1', 'id', 'string', 0, 0, NOW()),
(1, 'f2', 'Tag2', 'id', 'string', 0, 1, NOW()),
(1, 'f3', 'Tag3', 'id', 'string', 0, 1, NOW())");
var detail = _service.GetById(1);
Assert.Equal(3, detail.Mappings.Count);
Assert.Equal(1, detail.Mappings.Count(m => m.IsEnabled == 0));
Assert.Equal(2, detail.Mappings.Count(m => m.IsEnabled == 1));
}
// ======== 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);
}
}
}