ec4c8fab87
Move configuration options from Core/DataAccess/DataSync/ExcelIO to dedicated Options folders within each project for better organization. Update all references and tests accordingly.
229 lines
6.8 KiB
C#
229 lines
6.8 KiB
C#
using JdeScoping.DataAccess.Options;
|
|
using JdeScoping.DataAccess.Exceptions;
|
|
using JdeScoping.DataAccess.Interfaces;
|
|
using JdeScoping.DataAccess.Repositories;
|
|
using Microsoft.Extensions.Logging;
|
|
using Microsoft.Extensions.Options;
|
|
using NSubstitute;
|
|
using NSubstitute.ExceptionExtensions;
|
|
using Shouldly;
|
|
using Xunit;
|
|
|
|
namespace JdeScoping.DataAccess.Tests;
|
|
|
|
/// <summary>
|
|
/// Unit tests for CmsRepository.
|
|
/// </summary>
|
|
public class CmsRepositoryTests
|
|
{
|
|
private readonly IDbConnectionFactory _connectionFactory;
|
|
private readonly ILogger<CmsRepository> _logger;
|
|
private readonly IOptions<DataAccessOptions> _options;
|
|
|
|
public CmsRepositoryTests()
|
|
{
|
|
_connectionFactory = Substitute.For<IDbConnectionFactory>();
|
|
_logger = Substitute.For<ILogger<CmsRepository>>();
|
|
_options = Microsoft.Extensions.Options.Options.Create(new DataAccessOptions
|
|
{
|
|
DefaultTimeoutSeconds = 30,
|
|
MisDataTimeoutSeconds = 60000
|
|
});
|
|
}
|
|
|
|
#region Constructor Tests
|
|
|
|
[Fact]
|
|
public void Constructor_NullConnectionFactory_ThrowsArgumentNullException()
|
|
{
|
|
// Act & Assert
|
|
Should.Throw<ArgumentNullException>(
|
|
() => new CmsRepository(null!, _logger, _options))
|
|
.ParamName.ShouldBe("connectionFactory");
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_NullLogger_ThrowsArgumentNullException()
|
|
{
|
|
// Act & Assert
|
|
Should.Throw<ArgumentNullException>(
|
|
() => new CmsRepository(_connectionFactory, null!, _options))
|
|
.ParamName.ShouldBe("logger");
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_NullOptions_ThrowsArgumentNullException()
|
|
{
|
|
// Act & Assert
|
|
Should.Throw<ArgumentNullException>(
|
|
() => new CmsRepository(_connectionFactory, _logger, null!))
|
|
.ParamName.ShouldBe("options");
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_ValidParameters_CreatesInstance()
|
|
{
|
|
// Act
|
|
var repository = new CmsRepository(_connectionFactory, _logger, _options);
|
|
|
|
// Assert
|
|
repository.ShouldNotBeNull();
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region GetMisDataAsync Tests
|
|
|
|
[Fact]
|
|
public async Task GetMisDataAsync_ConnectionFails_ThrowsConnectionException()
|
|
{
|
|
// Arrange
|
|
_connectionFactory.CreateCmsConnectionAsync(Arg.Any<CancellationToken>())
|
|
.ThrowsAsync(new ConnectionException("Test connection error", "CMS"));
|
|
|
|
var repository = new CmsRepository(_connectionFactory, _logger, _options);
|
|
|
|
// Act & Assert
|
|
var ex = await Should.ThrowAsync<ConnectionException>(
|
|
async () =>
|
|
{
|
|
await foreach (var _ in repository.GetMisDataAsync())
|
|
{
|
|
}
|
|
});
|
|
|
|
ex.DataSource.ShouldBe("CMS");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetMisDataAsync_UsesCmsConnection()
|
|
{
|
|
// Arrange
|
|
_connectionFactory.CreateCmsConnectionAsync(Arg.Any<CancellationToken>())
|
|
.ThrowsAsync(new ConnectionException("Test connection error", "CMS"));
|
|
|
|
var repository = new CmsRepository(_connectionFactory, _logger, _options);
|
|
|
|
// Act
|
|
try
|
|
{
|
|
await foreach (var _ in repository.GetMisDataAsync())
|
|
{
|
|
}
|
|
}
|
|
catch (ConnectionException)
|
|
{
|
|
// Expected
|
|
}
|
|
|
|
// Assert - verify correct connection factory method was called
|
|
await _connectionFactory.Received(1).CreateCmsConnectionAsync(Arg.Any<CancellationToken>());
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Cancellation Tests
|
|
|
|
[Fact]
|
|
public async Task GetMisDataAsync_CancellationRequested_ThrowsOperationCanceledException()
|
|
{
|
|
// Arrange
|
|
using var cts = new CancellationTokenSource();
|
|
cts.Cancel();
|
|
|
|
_connectionFactory.CreateCmsConnectionAsync(Arg.Any<CancellationToken>())
|
|
.ThrowsAsync(new OperationCanceledException(cts.Token));
|
|
|
|
var repository = new CmsRepository(_connectionFactory, _logger, _options);
|
|
|
|
// Act & Assert
|
|
await Should.ThrowAsync<OperationCanceledException>(
|
|
async () =>
|
|
{
|
|
await foreach (var _ in repository.GetMisDataAsync(ct: cts.Token))
|
|
{
|
|
}
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Incremental Sync Tests
|
|
|
|
[Fact]
|
|
public async Task GetMisDataAsync_WithLastUpdateDT_UsesFilteredQuery()
|
|
{
|
|
// Arrange
|
|
var lastUpdate = new DateTime(2024, 1, 15, 10, 30, 0);
|
|
_connectionFactory.CreateCmsConnectionAsync(Arg.Any<CancellationToken>())
|
|
.ThrowsAsync(new ConnectionException("Test connection error", "CMS"));
|
|
|
|
var repository = new CmsRepository(_connectionFactory, _logger, _options);
|
|
|
|
// Act & Assert - this just verifies the method accepts the parameter
|
|
await Should.ThrowAsync<ConnectionException>(
|
|
async () =>
|
|
{
|
|
await foreach (var _ in repository.GetMisDataAsync(lastUpdate))
|
|
{
|
|
}
|
|
});
|
|
}
|
|
|
|
[Fact]
|
|
public async Task GetMisDataAsync_WithoutLastUpdateDT_UsesFullQuery()
|
|
{
|
|
// Arrange
|
|
_connectionFactory.CreateCmsConnectionAsync(Arg.Any<CancellationToken>())
|
|
.ThrowsAsync(new ConnectionException("Test connection error", "CMS"));
|
|
|
|
var repository = new CmsRepository(_connectionFactory, _logger, _options);
|
|
|
|
// Act & Assert
|
|
await Should.ThrowAsync<ConnectionException>(
|
|
async () =>
|
|
{
|
|
await foreach (var _ in repository.GetMisDataAsync())
|
|
{
|
|
}
|
|
});
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Timeout Configuration Tests
|
|
|
|
[Fact]
|
|
public void Constructor_UsesMisDataTimeout()
|
|
{
|
|
// Arrange
|
|
var customOptions = Microsoft.Extensions.Options.Options.Create(new DataAccessOptions
|
|
{
|
|
MisDataTimeoutSeconds = 999999
|
|
});
|
|
|
|
// Act
|
|
var repository = new CmsRepository(_connectionFactory, _logger, customOptions);
|
|
|
|
// Assert
|
|
repository.ShouldNotBeNull();
|
|
// The timeout value is internal, verified through behavior
|
|
}
|
|
|
|
[Fact]
|
|
public void Constructor_DefaultMisDataTimeout_Is60000Seconds()
|
|
{
|
|
// Arrange
|
|
var defaultOptions = Microsoft.Extensions.Options.Options.Create(new DataAccessOptions());
|
|
|
|
// Act
|
|
var repository = new CmsRepository(_connectionFactory, _logger, defaultOptions);
|
|
|
|
// Assert
|
|
repository.ShouldNotBeNull();
|
|
// Default timeout of 60000 seconds is verified implicitly
|
|
}
|
|
|
|
#endregion
|
|
}
|