#region << 版 本 注 释 >> /*-------------------------------------------------------------------- |* 版权所有 (c) 2026 WenJY 保留所有权利。 |* CLR版本:4.0.30319.42000 |* 机器名称:Mr.Wen's MacBook Pro |* 命名空间:Sln.Wcs.Business.Tests |* 唯一标识: |* |* 创建者:WenJY |* 电子邮箱: |* 创建时间:2026-05-17 |* 版本:V1.0.0 |* 描述:StoreTaskBusiness 单元测试 |* |*-------------------------------------------------------------------- |* 修改人: |* 时间: |* 修改说明: |* |* 版本:V1.0.0 |*--------------------------------------------------------------------*/ #endregion << 版 本 注 释 >> using Moq; using Sln.Wcs.Business.Domain.Dto.CreateTask; using Sln.Wcs.Business.Domain.Dto.FilterLocation; using Sln.Wcs.Business.Domain.Dto.SaveTask; using Sln.Wcs.Business.Domain.Enum; using Sln.Wcs.Model.Domain; using Sln.Wcs.Repository.service; using Xunit; namespace Sln.Wcs.Business.Tests; /// /// 可测试的 StoreTaskBusiness 子类,用于访问 protected 方法 /// public class TestableStoreTaskBusiness : StoreTaskBusiness { public TestableStoreTaskBusiness( IBasePathInfoService basePathInfoService, ILiveTaskQueueService liveTaskQueueService, IBaseStoreInfoService baseStoreInfoService) : base(basePathInfoService, liveTaskQueueService, baseStoreInfoService) { } public void PublicValidateCreateTaskParams(CreateTaskDto dto) => ValidateCreateTaskParams(dto); public void PublicValidateFilterLocationParams(FilterLocationDto dto) => ValidateFilterLocationParams(dto); public string PublicGenerateTaskCode() => GenerateTaskCode(); public string PublicGetCategoryName(TaskCategoryEnum category) => GetCategoryName(category); public string PublicGetTaskTypeName(TaskTypeEnum taskType) => GetTaskTypeName(taskType); public string PublicGetTaskSuccessMessage( string taskCode, string pathName, TaskTypeEnum taskType, TaskCategoryEnum taskCategory) => GetTaskSuccessMessage(taskCode, pathName, taskType, taskCategory); public BasePathInfo PublicGetPathInfo( CreateTaskDto createTaskDto, TaskTypeEnum taskType, TaskCategoryEnum taskCategory) => GetPathInfo(createTaskDto, taskType, taskCategory); } public class StoreTaskBusinessTests { private readonly Mock _mockBasePathInfoService; private readonly Mock _mockLiveTaskQueueService; private readonly Mock _mockBaseStoreInfoService; private readonly TestableStoreTaskBusiness _storeTaskBusiness; public StoreTaskBusinessTests() { _mockBasePathInfoService = new Mock(); _mockLiveTaskQueueService = new Mock(); _mockBaseStoreInfoService = new Mock(); _storeTaskBusiness = new TestableStoreTaskBusiness( _mockBasePathInfoService.Object, _mockLiveTaskQueueService.Object, _mockBaseStoreInfoService.Object); } #region GetCategoryName 测试 [Theory] [InlineData(TaskCategoryEnum.Material, "包材")] [InlineData(TaskCategoryEnum.Product, "成品")] [InlineData(TaskCategoryEnum.Pallet, "托盘")] public void GetCategoryName_ValidCategory_ReturnsCorrectName(TaskCategoryEnum category, string expected) { var result = _storeTaskBusiness.PublicGetCategoryName(category); Assert.Equal(expected, result); } #endregion #region GetTaskTypeName 测试 [Theory] [InlineData(TaskTypeEnum.InStore, "入库")] [InlineData(TaskTypeEnum.OutStore, "出库")] public void GetTaskTypeName_ValidType_ReturnsCorrectName(TaskTypeEnum taskType, string expected) { var result = _storeTaskBusiness.PublicGetTaskTypeName(taskType); Assert.Equal(expected, result); } #endregion #region ValidateCreateTaskParams 测试 [Fact] public void ValidateCreateTaskParams_NullMaterialCode_ThrowsException() { var dto = new CreateTaskDto { materialCode = null!, palletBarcode = "PLT001", startPoint = "A", endPoint = "B" }; var exception = Assert.Throws(() => _storeTaskBusiness.PublicValidateCreateTaskParams(dto)); Assert.Contains("物料编号不允许为 NULL", exception.Message); } [Fact] public void ValidateCreateTaskParams_NullPalletBarcode_ThrowsException() { var dto = new CreateTaskDto { materialCode = "MAT001", palletBarcode = null!, startPoint = "A", endPoint = "B", taskCategory = TaskCategoryEnum.Material }; var exception = Assert.Throws(() => _storeTaskBusiness.PublicValidateCreateTaskParams(dto)); Assert.Contains("条码不允许为 NULL", exception.Message); } [Fact] public void ValidateCreateTaskParams_NullStartPoint_ThrowsException() { var dto = new CreateTaskDto { materialCode = "MAT001", palletBarcode = "PLT001", startPoint = null!, endPoint = "B" }; var exception = Assert.Throws(() => _storeTaskBusiness.PublicValidateCreateTaskParams(dto)); Assert.Contains("起始位置、终点位置不允许为 NULL", exception.Message); } [Fact] public void ValidateCreateTaskParams_EmptyEndPoint_ThrowsException() { var dto = new CreateTaskDto { materialCode = "MAT001", palletBarcode = "PLT001", startPoint = "A", endPoint = "" }; var exception = Assert.Throws(() => _storeTaskBusiness.PublicValidateCreateTaskParams(dto)); Assert.Contains("起始位置、终点位置不允许为 NULL", exception.Message); } [Fact] public void ValidateCreateTaskParams_ValidParams_NoException() { var dto = new CreateTaskDto { materialCode = "MAT001", palletBarcode = "PLT001", startPoint = "A", endPoint = "B", taskCategory = TaskCategoryEnum.Material }; var exception = Record.Exception(() => _storeTaskBusiness.PublicValidateCreateTaskParams(dto)); Assert.Null(exception); } #endregion #region ValidateFilterLocationParams 测试 [Fact] public void ValidateFilterLocationParams_NullMaterialCode_ThrowsException() { var dto = new FilterLocationDto { materialCode = null! }; var exception = Assert.Throws(() => _storeTaskBusiness.PublicValidateFilterLocationParams(dto)); Assert.Contains("物料编号不允许为 NULL", exception.Message); } [Fact] public void ValidateFilterLocationParams_ValidParams_NoException() { var dto = new FilterLocationDto { materialCode = "MAT001" }; var exception = Record.Exception(() => _storeTaskBusiness.PublicValidateFilterLocationParams(dto)); Assert.Null(exception); } #endregion #region GenerateTaskCode 测试 [Fact] public void GenerateTaskCode_ReturnsCorrectFormat() { var taskCode = _storeTaskBusiness.PublicGenerateTaskCode(); Assert.NotNull(taskCode); Assert.Equal(18, taskCode.Length); Assert.True(long.TryParse(taskCode[..14], out _)); Assert.True(int.TryParse(taskCode[14..], out var randomPart)); Assert.InRange(randomPart, 1000, 9999); } [Fact] public void GenerateTaskCode_MultipleCalls_GeneratesUniqueCodes() { var codes = new HashSet(); for (int i = 0; i < 100; i++) { codes.Add(_storeTaskBusiness.PublicGenerateTaskCode()); } Assert.Equal(100, codes.Count); } #endregion #region CreateTask 测试 [Fact] public void CreateTask_ValidInput_ReturnsSuccessResult() { var dto = new CreateTaskDto { materialCode = "MAT001", materialBarcode = "MAT001BAR", palletBarcode = "PLT001", amount = 100, startPoint = "START", endPoint = "END", taskType = TaskTypeEnum.InStore, taskCategory = TaskCategoryEnum.Material }; var pathDetails = new List { new BasePathDetails { objId = 1, pathCode = "PATH1", startPoint = "START", endPoint = "MID", deviceType = 0 }, new BasePathDetails { objId = 2, pathCode = "PATH2", startPoint = "MID", endPoint = "END", deviceType = 0 } }; var pathInfo = new BasePathInfo { objId = 1, pathCode = "MAIN_PATH", pathName = "主输送线", pathType = 1, pathCategory = 1, startPoint = "START", endPoint = "END", pathDetails = pathDetails }; _mockBasePathInfoService .Setup(x => x.GetBasePathInfo(It.IsAny>>())) .Returns(new List { pathInfo }); var result = _storeTaskBusiness.CreateTask(dto); Assert.Equal(BusinessStatusEnum.成功, result.code); Assert.NotNull(result.data); Assert.NotNull(result.data.taskCode); Assert.Equal(2, result.data.taskDetails.Count); Assert.Equal(2, result.data.taskQueue.taskSteps); } [Fact] public void CreateTask_PathNotFound_ReturnsErrorResult() { var dto = new CreateTaskDto { materialCode = "MAT001", palletBarcode = "PLT001", startPoint = "INVALID", endPoint = "INVALID", taskType = TaskTypeEnum.InStore, taskCategory = TaskCategoryEnum.Material }; _mockBasePathInfoService .Setup(x => x.GetBasePathInfo(It.IsAny>>())) .Returns(new List()); var result = _storeTaskBusiness.CreateTask(dto); Assert.Equal(BusinessStatusEnum.方法执行异常, result.code); Assert.Contains("输送路径为 NULL", result.msg); } #endregion #region FilterLocation 测试 [Fact] public void FilterLocation_ValidInput_ReturnsSuccessResult() { var dto = new FilterLocationDto { materialCode = "MAT001", taskType = TaskTypeEnum.InStore, taskCategory = TaskCategoryEnum.Material }; var locationInfos = new List { new BaseLocationInfo { locationCode = "LOC001", locationRows = 1, locationColumns = 1, locationLayers = 1, locationStatus = 0, materialCode = "MAT001", isFlag = 1 } }; var storeInfo = new BaseStoreInfo { storeCode = "STORE001", storeName = "测试仓库", storeType = 1, isFlag = 1, locationInfos = locationInfos }; _mockBaseStoreInfoService .Setup(x => x.GetBasePathInfo( It.IsAny>>(), It.IsAny>>())) .Returns(new List { storeInfo }); var result = _storeTaskBusiness.FilterLocation(dto); Assert.Equal(BusinessStatusEnum.成功, result.code); Assert.NotNull(result.data); Assert.NotNull(result.data.storeInfo); Assert.NotNull(result.data.locationInfo); Assert.Single(result.data.locationInfos); } [Fact] public void FilterLocation_NoAvailableStore_ReturnsErrorResult() { var dto = new FilterLocationDto { materialCode = "MAT001", taskType = TaskTypeEnum.InStore, taskCategory = TaskCategoryEnum.Material }; _mockBaseStoreInfoService .Setup(x => x.GetBasePathInfo( It.IsAny>>(), It.IsAny>>())) .Returns(new List()); var result = _storeTaskBusiness.FilterLocation(dto); Assert.Equal(BusinessStatusEnum.方法执行异常, result.code); Assert.Contains("未获取到可用仓库", result.msg); } #endregion #region SaveTask 测试 [Fact] public void SaveTask_ValidInput_ReturnsSuccessResult() { var dto = new SaveTaskDto { taskQueue = new LiveTaskQueue { taskCode = "TASK001", materialCode = "MAT001", palletBarcode = "PLT001", startPoint = "A", endPoint = "B", taskType = 1, taskCategory = 1 } }; _mockLiveTaskQueueService .Setup(x => x.InsertTaskQueue(It.IsAny())) .Returns(true); var result = _storeTaskBusiness.SaveTask(dto); Assert.Equal(BusinessStatusEnum.成功, result.code); Assert.NotNull(result.data); Assert.True(result.data.isRes); } [Fact] public void SaveTask_InsertFails_ReturnsFalse() { var dto = new SaveTaskDto { taskQueue = new LiveTaskQueue { taskCode = "TASK001", materialCode = "MAT001", palletBarcode = "PLT001", startPoint = "A", endPoint = "B", taskType = 1, taskCategory = 1 } }; _mockLiveTaskQueueService .Setup(x => x.InsertTaskQueue(It.IsAny())) .Returns(false); var result = _storeTaskBusiness.SaveTask(dto); Assert.Equal(BusinessStatusEnum.成功, result.code); Assert.NotNull(result.data); Assert.False(result.data.isRes); } #endregion #region GetTaskSuccessMessage 测试 [Fact] public void GetTaskSuccessMessage_ReturnsCorrectMessage() { var message = _storeTaskBusiness.PublicGetTaskSuccessMessage( "TASK001", "主输送线", TaskTypeEnum.InStore, TaskCategoryEnum.Material); Assert.Equal("包材入库任务创建成功:TASK001;关联路径:主输送线", message); } [Fact] public void GetTaskSuccessMessage_ProductOutStore_ReturnsCorrectMessage() { var message = _storeTaskBusiness.PublicGetTaskSuccessMessage( "TASK002", "成品出库线", TaskTypeEnum.OutStore, TaskCategoryEnum.Product); Assert.Equal("成品出库任务创建成功:TASK002;关联路径:成品出库线", message); } #endregion }