#0040 增加测试用例

This commit is contained in:
zhengxuan.zhang
2026-03-18 20:41:05 +08:00
parent 67898edc3f
commit 180501808e
8 changed files with 121 additions and 1621 deletions
@@ -3,6 +3,7 @@ using System.Windows;
using Moq;
using Serilog;
using Xunit;
using Xunit.Abstractions;
using XP.Hardware.RaySource.Services;
using XplorePlane.Models;
using XplorePlane.Services.AppState;
@@ -18,9 +19,12 @@ namespace XplorePlane.Tests.Services
private readonly AppStateService _service;
private readonly Mock<IRaySourceService> _mockRaySource;
private readonly Mock<ILogger> _mockLogger;
private readonly ITestOutputHelper _output;
public AppStateServiceTests()
public AppStateServiceTests(ITestOutputHelper output)
{
_output = output;
// Ensure WPF Application exists for Dispatcher
if (Application.Current == null)
{
@@ -42,24 +46,28 @@ namespace XplorePlane.Tests.Services
[Fact]
public void DefaultState_MotionState_IsDefault()
{
_output.WriteLine($"MotionState == MotionState.Default: {ReferenceEquals(MotionState.Default, _service.MotionState)}");
Assert.Same(MotionState.Default, _service.MotionState);
}
[Fact]
public void DefaultState_RaySourceState_IsDefault()
{
_output.WriteLine($"RaySourceState == RaySourceState.Default: {ReferenceEquals(RaySourceState.Default, _service.RaySourceState)}");
Assert.Same(RaySourceState.Default, _service.RaySourceState);
}
[Fact]
public void DefaultState_SystemState_IsDefault()
{
_output.WriteLine($"SystemState == SystemState.Default: {ReferenceEquals(SystemState.Default, _service.SystemState)}");
Assert.Same(SystemState.Default, _service.SystemState);
}
[Fact]
public void DefaultState_CalibrationMatrix_IsNull()
{
_output.WriteLine($"CalibrationMatrix: {_service.CalibrationMatrix?.ToString() ?? "null"}");
Assert.Null(_service.CalibrationMatrix);
}
@@ -68,25 +76,29 @@ namespace XplorePlane.Tests.Services
[Fact]
public void UpdateMotionState_NullArgument_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => _service.UpdateMotionState(null!));
var ex = Assert.Throws<ArgumentNullException>(() => _service.UpdateMotionState(null!));
_output.WriteLine($"UpdateMotionState(null) threw: {ex.GetType().Name}, Param={ex.ParamName}");
}
[Fact]
public void UpdateRaySourceState_NullArgument_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => _service.UpdateRaySourceState(null!));
var ex = Assert.Throws<ArgumentNullException>(() => _service.UpdateRaySourceState(null!));
_output.WriteLine($"UpdateRaySourceState(null) threw: {ex.GetType().Name}, Param={ex.ParamName}");
}
[Fact]
public void UpdateDetectorState_NullArgument_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => _service.UpdateDetectorState(null!));
var ex = Assert.Throws<ArgumentNullException>(() => _service.UpdateDetectorState(null!));
_output.WriteLine($"UpdateDetectorState(null) threw: {ex.GetType().Name}, Param={ex.ParamName}");
}
[Fact]
public void UpdateSystemState_NullArgument_ThrowsArgumentNullException()
{
Assert.Throws<ArgumentNullException>(() => _service.UpdateSystemState(null!));
var ex = Assert.Throws<ArgumentNullException>(() => _service.UpdateSystemState(null!));
_output.WriteLine($"UpdateSystemState(null) threw: {ex.GetType().Name}, Param={ex.ParamName}");
}
// ── Dispose 后 Update 被忽略 ──
@@ -96,11 +108,13 @@ namespace XplorePlane.Tests.Services
{
var originalState = _service.MotionState;
_service.Dispose();
_output.WriteLine("Service disposed, attempting UpdateMotionState...");
// Should not throw, and state should remain unchanged
var newState = new MotionState(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12);
_service.UpdateMotionState(newState);
_output.WriteLine($"State unchanged after dispose: {ReferenceEquals(originalState, _service.MotionState)}");
Assert.Same(originalState, _service.MotionState);
}
@@ -114,6 +128,7 @@ namespace XplorePlane.Tests.Services
_service.RequestLinkedView(100.0, 200.0);
_output.WriteLine($"RequestLinkedView(100, 200) without CalibrationMatrix: HasError={_service.SystemState.HasError}, ErrorMessage='{_service.SystemState.ErrorMessage}'");
Assert.True(_service.SystemState.HasError);
Assert.NotEmpty(_service.SystemState.ErrorMessage);
}
@@ -4,6 +4,7 @@ using System.Threading.Tasks;
using Moq;
using Serilog;
using Xunit;
using Xunit.Abstractions;
using XplorePlane.Models;
using XplorePlane.Services;
using XplorePlane.Services.AppState;
@@ -21,9 +22,11 @@ namespace XplorePlane.Tests.Services
private readonly Mock<IPipelineExecutionService> _mockPipeline;
private readonly Mock<ILogger> _mockLogger;
private readonly RecipeService _service;
private readonly ITestOutputHelper _output;
public RecipeServiceTests()
public RecipeServiceTests(ITestOutputHelper output)
{
_output = output;
_mockAppState = new Mock<IAppStateService>();
_mockPipeline = new Mock<IPipelineExecutionService>();
_mockLogger = new Mock<ILogger>();
@@ -45,6 +48,7 @@ namespace XplorePlane.Tests.Services
public void CreateRecipe_ValidName_ReturnsEmptyRecipe()
{
var recipe = _service.CreateRecipe("TestRecipe");
_output.WriteLine($"CreateRecipe('TestRecipe'): Name={recipe.Name}, Id={recipe.Id}, Steps.Count={recipe.Steps.Count}, CreatedAt={recipe.CreatedAt}");
Assert.Equal("TestRecipe", recipe.Name);
Assert.Empty(recipe.Steps);
@@ -56,19 +60,22 @@ namespace XplorePlane.Tests.Services
[Fact]
public void CreateRecipe_EmptyName_ThrowsArgumentException()
{
Assert.Throws<ArgumentException>(() => _service.CreateRecipe(string.Empty));
var ex = Assert.Throws<ArgumentException>(() => _service.CreateRecipe(string.Empty));
_output.WriteLine($"CreateRecipe('') threw: {ex.GetType().Name}, Message={ex.Message}");
}
[Fact]
public void CreateRecipe_NullName_ThrowsArgumentException()
{
Assert.Throws<ArgumentException>(() => _service.CreateRecipe(null!));
var ex = Assert.Throws<ArgumentException>(() => _service.CreateRecipe(null!));
_output.WriteLine($"CreateRecipe(null) threw: {ex.GetType().Name}, Message={ex.Message}");
}
[Fact]
public void CreateRecipe_WhitespaceName_ThrowsArgumentException()
{
Assert.Throws<ArgumentException>(() => _service.CreateRecipe(" "));
var ex = Assert.Throws<ArgumentException>(() => _service.CreateRecipe(" "));
_output.WriteLine($"CreateRecipe(' ') threw: {ex.GetType().Name}, Message={ex.Message}");
}
// ── RecordCurrentStep 验证 ──
@@ -88,6 +95,7 @@ namespace XplorePlane.Tests.Services
var pipeline = new PipelineModel { Name = "TestPipeline" };
var step = _service.RecordCurrentStep(recipe, pipeline);
_output.WriteLine($"RecordCurrentStep: StepIndex={step.StepIndex}, MotionState.XM={step.MotionState.XM}, RaySource.Voltage={step.RaySourceState.Voltage}, Detector.Resolution={step.DetectorState.Resolution}, Pipeline={step.Pipeline.Name}");
Assert.Equal(0, step.StepIndex);
Assert.Same(motionState, step.MotionState);
@@ -102,9 +110,11 @@ namespace XplorePlane.Tests.Services
public async Task LoadAsync_FileNotExists_ThrowsFileNotFoundException()
{
var nonExistentPath = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString() + ".json");
_output.WriteLine($"LoadAsync 不存在的文件: {nonExistentPath}");
await Assert.ThrowsAsync<FileNotFoundException>(
var ex = await Assert.ThrowsAsync<FileNotFoundException>(
() => _service.LoadAsync(nonExistentPath));
_output.WriteLine($"抛出异常: {ex.GetType().Name}, Message={ex.Message}");
}
[Fact]
@@ -114,9 +124,11 @@ namespace XplorePlane.Tests.Services
try
{
await File.WriteAllTextAsync(tempFile, "{ this is not valid json !!! }");
_output.WriteLine($"LoadAsync 无效JSON文件: {tempFile}");
await Assert.ThrowsAsync<InvalidDataException>(
var ex = await Assert.ThrowsAsync<InvalidDataException>(
() => _service.LoadAsync(tempFile));
_output.WriteLine($"抛出异常: {ex.GetType().Name}, Message={ex.Message}");
}
finally
{