137 lines
5.1 KiB
C#
137 lines
5.1 KiB
C#
using System;
|
|
using System.Windows;
|
|
using Moq;
|
|
using Serilog;
|
|
using Xunit;
|
|
using Xunit.Abstractions;
|
|
using XP.Hardware.RaySource.Services;
|
|
using XplorePlane.Models;
|
|
using XplorePlane.Services.AppState;
|
|
|
|
namespace XplorePlane.Tests.Services
|
|
{
|
|
/// <summary>
|
|
/// AppStateService 单元测试。
|
|
/// 验证默认状态值、Dispose 后行为、null 参数校验、CalibrationMatrix 缺失时的错误处理。
|
|
/// </summary>
|
|
public class AppStateServiceTests : IDisposable
|
|
{
|
|
private readonly AppStateService _service;
|
|
private readonly Mock<IRaySourceService> _mockRaySource;
|
|
private readonly Mock<ILogger> _mockLogger;
|
|
private readonly ITestOutputHelper _output;
|
|
|
|
public AppStateServiceTests(ITestOutputHelper output)
|
|
{
|
|
_output = output;
|
|
|
|
// Ensure WPF Application exists for Dispatcher
|
|
if (Application.Current == null)
|
|
{
|
|
new Application();
|
|
}
|
|
|
|
_mockRaySource = new Mock<IRaySourceService>();
|
|
_mockLogger = new Mock<ILogger>();
|
|
_service = new AppStateService(_mockRaySource.Object, _mockLogger.Object);
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
_service.Dispose();
|
|
}
|
|
|
|
// ── 默认状态值验证 ──
|
|
|
|
[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);
|
|
}
|
|
|
|
// ── null 参数抛出 ArgumentNullException ──
|
|
|
|
[Fact]
|
|
public void UpdateMotionState_NullArgument_ThrowsArgumentNullException()
|
|
{
|
|
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()
|
|
{
|
|
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()
|
|
{
|
|
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()
|
|
{
|
|
var ex = Assert.Throws<ArgumentNullException>(() => _service.UpdateSystemState(null!));
|
|
_output.WriteLine($"UpdateSystemState(null) threw: {ex.GetType().Name}, Param={ex.ParamName}");
|
|
}
|
|
|
|
// ── Dispose 后 Update 被忽略 ──
|
|
|
|
[Fact]
|
|
public void Dispose_ThenUpdate_IsIgnored()
|
|
{
|
|
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);
|
|
}
|
|
|
|
// ── CalibrationMatrix 为 null 时 RequestLinkedView 设置错误状态 ──
|
|
|
|
[Fact]
|
|
public void RequestLinkedView_NoCalibrationMatrix_SetsErrorState()
|
|
{
|
|
// CalibrationMatrix is null by default
|
|
Assert.Null(_service.CalibrationMatrix);
|
|
|
|
_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);
|
|
}
|
|
}
|
|
}
|