using System.Data; using JdeScoping.DataAccess.Interfaces; using JdeScoping.DataSync.Etl.Destinations; using NSubstitute; namespace JdeScoping.DataSync.Tests.Etl.Destinations; public class DbBulkImportDestinationTests { /// /// This test documents that column mapping is applied to ignore extra source columns. /// The actual functionality requires a database connection and is an integration test concept. /// The implementation fetches destination columns from INFORMATION_SCHEMA.COLUMNS /// and only maps columns that exist in both source and destination. /// [Fact] public void WriteAsync_SourceHasExtraColumns_IgnoresExtraColumns_IntegrationTestConcept() { // This is an integration test concept - // The actual behavior verifies that column mappings are applied: // 1. GetDestinationColumnsAsync fetches columns from INFORMATION_SCHEMA.COLUMNS // 2. Column mappings only added for columns in destination (case-insensitive) // 3. Extra source columns are silently ignored during bulk copy // // To test this fully, an integration test with a real database is required. // The unit test here just verifies the component can be constructed. var factory = Substitute.For(); var dest = new DbBulkImportDestination(factory, "TestTable"); Assert.NotNull(dest); } [Fact] public void Constructor_SetsDestinationName() { var factory = Substitute.For(); var dest = new DbBulkImportDestination(factory, "WorkOrder"); Assert.Equal("BulkImport:WorkOrder", dest.DestinationName); } [Fact] public void Constructor_NullFactory_ThrowsArgumentNullException() { Assert.Throws(() => new DbBulkImportDestination(null!, "WorkOrder")); } [Fact] public void Constructor_NullTableName_ThrowsArgumentNullException() { var factory = Substitute.For(); Assert.Throws(() => new DbBulkImportDestination(factory, null!)); } [Fact] public void Constructor_EmptyTableName_ThrowsArgumentException() { var factory = Substitute.For(); Assert.Throws(() => new DbBulkImportDestination(factory, "")); } [Theory] [InlineData(0)] // 0 means default [InlineData(5000)] [InlineData(50000)] public void Constructor_VariousBatchSizes_Succeeds(int batchSize) { var factory = Substitute.For(); var dest = new DbBulkImportDestination(factory, "WorkOrder", batchSize: batchSize); Assert.NotNull(dest); } [Fact] public void Constructor_CustomTimeout_SetsTimeout() { // Arrange & Act var factory = Substitute.For(); var dest = new DbBulkImportDestination( factory, "TestTable", commandTimeoutSeconds: 1800); // Assert - can't directly test private field, but constructor should accept it Assert.NotNull(dest); } [Fact] public void Constructor_ZeroTimeout_UsesDefault() { // Arrange & Act var factory = Substitute.For(); var dest = new DbBulkImportDestination( factory, "TestTable", commandTimeoutSeconds: 0); // Assert Assert.NotNull(dest); } }