using Microsoft.Extensions.Logging.Abstractions; using NSubstitute; using ScadaLink.Commons.Types.Enums; using ScadaLink.DataConnectionLayer.Adapters; namespace ScadaLink.DataConnectionLayer.Tests; /// /// WP-8: Tests for LmxProxy adapter. /// public class LmxProxyDataConnectionTests { private readonly ILmxProxyClient _mockClient; private readonly ILmxProxyClientFactory _mockFactory; private readonly LmxProxyDataConnection _adapter; public LmxProxyDataConnectionTests() { _mockClient = Substitute.For(); _mockFactory = Substitute.For(); _mockFactory.Create().Returns(_mockClient); _adapter = new LmxProxyDataConnection(_mockFactory, NullLogger.Instance); } [Fact] public async Task Connect_OpensSessionWithHostAndPort() { _mockClient.OpenSessionAsync("myhost", 5001, Arg.Any()) .Returns("session-123"); _mockClient.IsConnected.Returns(true); await _adapter.ConnectAsync(new Dictionary { ["Host"] = "myhost", ["Port"] = "5001" }); Assert.Equal(ConnectionHealth.Connected, _adapter.Status); await _mockClient.Received(1).OpenSessionAsync("myhost", 5001, Arg.Any()); } [Fact] public async Task Disconnect_ClosesSession() { _mockClient.IsConnected.Returns(true); _mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any()) .Returns("session-123"); await _adapter.ConnectAsync(new Dictionary()); await _adapter.DisconnectAsync(); Assert.Equal(ConnectionHealth.Disconnected, _adapter.Status); await _mockClient.Received(1).CloseSessionAsync(Arg.Any()); } [Fact] public async Task Write_Success_ReturnsGoodResult() { _mockClient.IsConnected.Returns(true); _mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any()) .Returns("session-123"); _mockClient.WriteTagAsync("Tag1", 42, Arg.Any()) .Returns(true); await _adapter.ConnectAsync(new Dictionary()); var result = await _adapter.WriteAsync("Tag1", 42); Assert.True(result.Success); } [Fact] public async Task Write_Failure_ReturnsError() { _mockClient.IsConnected.Returns(true); _mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any()) .Returns("session-123"); _mockClient.WriteTagAsync("Tag1", 42, Arg.Any()) .Returns(false); await _adapter.ConnectAsync(new Dictionary()); var result = await _adapter.WriteAsync("Tag1", 42); Assert.False(result.Success); Assert.Equal("LmxProxy write failed", result.ErrorMessage); } [Fact] public async Task Read_Good_ReturnsValue() { _mockClient.IsConnected.Returns(true); _mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any()) .Returns("session-123"); _mockClient.ReadTagAsync("Tag1", Arg.Any()) .Returns((42.5, DateTime.UtcNow, true)); await _adapter.ConnectAsync(new Dictionary()); var result = await _adapter.ReadAsync("Tag1"); Assert.True(result.Success); Assert.Equal(42.5, result.Value!.Value); } [Fact] public async Task Read_Bad_ReturnsFailure() { _mockClient.IsConnected.Returns(true); _mockClient.OpenSessionAsync(Arg.Any(), Arg.Any(), Arg.Any()) .Returns("session-123"); _mockClient.ReadTagAsync("Tag1", Arg.Any()) .Returns((null, DateTime.UtcNow, false)); await _adapter.ConnectAsync(new Dictionary()); var result = await _adapter.ReadAsync("Tag1"); Assert.False(result.Success); } [Fact] public async Task NotConnected_ThrowsOnOperations() { _mockClient.IsConnected.Returns(false); await Assert.ThrowsAsync(() => _adapter.ReadAsync("tag1")); } }