Files
jdescopingtool/NEW/tests/JdeScoping.DataAccess.Tests/JdeRepositoryTests.cs
T
Joseph Doherty ec4c8fab87 refactor: relocate options classes to dedicated Options folders
Move configuration options from Core/DataAccess/DataSync/ExcelIO to
dedicated Options folders within each project for better organization.
Update all references and tests accordingly.
2026-01-03 08:55:08 -05:00

675 lines
21 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 JdeRepository.
/// </summary>
public class JdeRepositoryTests
{
private readonly IDbConnectionFactory _connectionFactory;
private readonly ILogger<JdeRepository> _logger;
private readonly IOptions<DataAccessOptions> _options;
public JdeRepositoryTests()
{
_connectionFactory = Substitute.For<IDbConnectionFactory>();
_logger = Substitute.For<ILogger<JdeRepository>>();
_options = Microsoft.Extensions.Options.Options.Create(new DataAccessOptions
{
DefaultTimeoutSeconds = 30,
LotUsageTimeoutSeconds = 60,
ProductionSchema = "PRODDTA",
ArchiveSchema = "ARCDTAPD",
StageSchema = "JDESTAGE"
});
}
#region Constructor Tests
[Fact]
public void Constructor_NullConnectionFactory_ThrowsArgumentNullException()
{
// Act & Assert
Should.Throw<ArgumentNullException>(
() => new JdeRepository(null!, _logger, _options))
.ParamName.ShouldBe("connectionFactory");
}
[Fact]
public void Constructor_NullLogger_ThrowsArgumentNullException()
{
// Act & Assert
Should.Throw<ArgumentNullException>(
() => new JdeRepository(_connectionFactory, null!, _options))
.ParamName.ShouldBe("logger");
}
[Fact]
public void Constructor_NullOptions_ThrowsArgumentNullException()
{
// Act & Assert
Should.Throw<ArgumentNullException>(
() => new JdeRepository(_connectionFactory, _logger, null!))
.ParamName.ShouldBe("options");
}
[Fact]
public void Constructor_ValidParameters_CreatesInstance()
{
// Act
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Assert
repository.ShouldNotBeNull();
}
#endregion
#region Schema Replacement Tests - Work Orders
[Fact]
public async Task GetWorkOrdersAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
var ex = await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrdersAsync())
{
}
});
ex.DataSource.ShouldBe("JDE");
}
[Fact]
public async Task GetWorkOrdersArchiveAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
var ex = await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrdersArchiveAsync())
{
}
});
ex.DataSource.ShouldBe("JDE");
}
#endregion
#region Schema Replacement Tests - Work Order Steps
[Fact]
public async Task GetWorkOrderStepsAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
var ex = await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrderStepsAsync())
{
}
});
ex.DataSource.ShouldBe("JDE");
}
[Fact]
public async Task GetWorkOrderStepsArchiveAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrderStepsArchiveAsync())
{
}
});
}
#endregion
#region Schema Replacement Tests - Work Order Times
[Fact]
public async Task GetWorkOrderTimesAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrderTimesAsync())
{
}
});
}
[Fact]
public async Task GetWorkOrderTimesArchiveAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrderTimesArchiveAsync())
{
}
});
}
#endregion
#region Schema Replacement Tests - Work Order Routings
[Fact]
public async Task GetWorkOrderRoutingsAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrderRoutingsAsync())
{
}
});
}
#endregion
#region Schema Replacement Tests - Work Order Components
[Fact]
public async Task GetWorkOrderComponentsAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrderComponentsAsync())
{
}
});
}
[Fact]
public async Task GetWorkOrderComponentsArchiveAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrderComponentsArchiveAsync())
{
}
});
}
#endregion
#region Schema Replacement Tests - Lots
[Fact]
public async Task GetLotsAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetLotsAsync())
{
}
});
}
#endregion
#region Schema Replacement Tests - Lot Usages
[Fact]
public async Task GetLotUsagesAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetLotUsagesAsync())
{
}
});
}
[Fact]
public async Task GetLotUsagesArchiveAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetLotUsagesArchiveAsync())
{
}
});
}
#endregion
#region JDE Stage Connection Tests - Lot Locations
[Fact]
public async Task GetLotLocationsAsync_UsesJdeStageConnection()
{
// Arrange
_connectionFactory.CreateJdeStageConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDEStage"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert - verify it uses Stage connection
var ex = await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetLotLocationsAsync())
{
}
});
ex.DataSource.ShouldBe("JDEStage");
}
#endregion
#region Reference Data Tests
[Fact]
public async Task GetItemsAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetItemsAsync())
{
}
});
}
[Fact]
public async Task GetUsersAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetUsersAsync())
{
}
});
}
[Fact]
public async Task GetBranchesAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetBranchesAsync())
{
}
});
}
[Fact]
public async Task GetProfitCentersAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetProfitCentersAsync())
{
}
});
}
[Fact]
public async Task GetWorkCentersAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkCentersAsync())
{
}
});
}
[Fact]
public async Task GetStatusCodesAsync_UsesJdeStageConnection()
{
// Arrange
_connectionFactory.CreateJdeStageConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDEStage"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert - verify it uses Stage connection
var ex = await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetStatusCodesAsync())
{
}
});
ex.DataSource.ShouldBe("JDEStage");
}
[Fact]
public async Task GetFunctionCodesAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetFunctionCodesAsync())
{
}
});
}
[Fact]
public async Task GetOrgHierarchyAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetOrgHierarchyAsync())
{
}
});
}
[Fact]
public async Task GetRouteMastersAsync_ConnectionFails_ThrowsConnectionException()
{
// Arrange
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetRouteMastersAsync())
{
}
});
}
#endregion
#region Cancellation Tests
[Fact]
public async Task GetWorkOrdersAsync_CancellationRequested_ThrowsOperationCanceledException()
{
// Arrange
using var cts = new CancellationTokenSource();
cts.Cancel();
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new OperationCanceledException(cts.Token));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<OperationCanceledException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrdersAsync(ct: cts.Token))
{
}
});
}
[Fact]
public async Task GetLotUsagesAsync_CancellationRequested_ThrowsOperationCanceledException()
{
// Arrange
using var cts = new CancellationTokenSource();
cts.Cancel();
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new OperationCanceledException(cts.Token));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<OperationCanceledException>(
async () =>
{
await foreach (var _ in repository.GetLotUsagesAsync(ct: cts.Token))
{
}
});
}
#endregion
#region Incremental Sync Tests
[Fact]
public async Task GetWorkOrdersAsync_WithLastUpdateDT_UsesFilteredQuery()
{
// Arrange
var lastUpdate = new DateTime(2024, 1, 15, 10, 30, 0);
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert - this just verifies the method accepts the parameter
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetWorkOrdersAsync(lastUpdate))
{
}
});
}
[Fact]
public async Task GetLotsAsync_WithLastUpdateDT_UsesFilteredQuery()
{
// Arrange
var lastUpdate = new DateTime(2024, 1, 15, 10, 30, 0);
_connectionFactory.CreateJdeConnectionAsync(Arg.Any<CancellationToken>())
.ThrowsAsync(new ConnectionException("Test connection error", "JDE"));
var repository = new JdeRepository(_connectionFactory, _logger, _options);
// Act & Assert
await Should.ThrowAsync<ConnectionException>(
async () =>
{
await foreach (var _ in repository.GetLotsAsync(lastUpdate))
{
}
});
}
#endregion
#region Options Configuration Tests
[Fact]
public void Constructor_UsesConfiguredSchemas()
{
// Arrange
var customOptions = Microsoft.Extensions.Options.Options.Create(new DataAccessOptions
{
ProductionSchema = "CUSTOM_PROD",
ArchiveSchema = "CUSTOM_ARC",
StageSchema = "CUSTOM_STG"
});
// Act
var repository = new JdeRepository(_connectionFactory, _logger, customOptions);
// Assert
repository.ShouldNotBeNull();
// The schema values are internal, verified through integration tests
}
[Fact]
public void Constructor_UsesConfiguredTimeouts()
{
// Arrange
var customOptions = Microsoft.Extensions.Options.Options.Create(new DataAccessOptions
{
DefaultTimeoutSeconds = 120,
LotUsageTimeoutSeconds = 999999
});
// Act
var repository = new JdeRepository(_connectionFactory, _logger, customOptions);
// Assert
repository.ShouldNotBeNull();
// The timeout values are internal, verified through integration tests
}
#endregion
}