Files
jdescopingtool/NEW/tests/JdeScoping.DataSync.Tests/Services/SchemaValidatorTests.cs
T
Joseph Doherty 26ff8d9b4f Initial commit: JDE Scoping Tool migration project
Set up repository with legacy .NET Framework 4.8 source (OLD/),
new .NET 10 Blazor solution (NEW/), OpenSpec specifications,
documentation, and project configuration.
2026-01-02 07:43:29 -05:00

278 lines
8.0 KiB
C#

using JdeScoping.DataSync.Models;
using JdeScoping.DataSync.Services;
namespace JdeScoping.DataSync.Tests.Services;
public class SchemaValidatorTests
{
private readonly SchemaValidator _validator = new();
private class TestEntity
{
public int Id { get; set; }
public string Name { get; set; } = string.Empty;
public string? NullableName { get; set; }
public decimal Amount { get; set; }
public DateTime CreatedDate { get; set; }
}
#region ValidateBatch Tests
[Fact]
public void ValidateBatch_EmptyData_ReturnsEmptyList()
{
// Arrange
var data = Array.Empty<TestEntity>();
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1)
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Empty(errors);
}
[Fact]
public void ValidateBatch_EmptySchema_ReturnsEmptyList()
{
// Arrange
var data = new List<TestEntity> { new() { Id = 1, Name = "Test" } };
var schema = Array.Empty<ColumnSchema>();
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Empty(errors);
}
[Fact]
public void ValidateBatch_ValidData_ReturnsEmptyList()
{
// Arrange
var data = new List<TestEntity>
{
new() { Id = 1, Name = "Test", Amount = 100.50m }
};
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1),
new("Name", "nvarchar", 50, null, null, false, 2),
new("Amount", "decimal", null, 10, 2, false, 3)
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Empty(errors);
}
[Fact]
public void ValidateBatch_StringTooLong_ReturnsError()
{
// Arrange
var data = new List<TestEntity>
{
new() { Id = 1, Name = "This is a very long string that exceeds the maximum length" }
};
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1),
new("Name", "nvarchar", 10, null, null, false, 2)
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Single(errors);
Assert.Equal("Name", errors[0].ColumnName);
Assert.Equal(0, errors[0].RowIndex);
Assert.Contains("exceeds maximum length", errors[0].Message);
}
[Fact]
public void ValidateBatch_NullInNonNullableColumn_ReturnsError()
{
// Arrange
var data = new List<TestEntity>
{
new() { Id = 1, Name = "" } // Empty string treated as null for non-nullable
};
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1),
new("Name", "nvarchar", 50, null, null, false, 2)
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Single(errors);
Assert.Equal("Name", errors[0].ColumnName);
Assert.Contains("does not allow null", errors[0].Message);
}
[Fact]
public void ValidateBatch_NullInNullableColumn_NoError()
{
// Arrange
var data = new List<TestEntity>
{
new() { Id = 1, Name = "Test", NullableName = null }
};
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1),
new("Name", "nvarchar", 50, null, null, false, 2),
new("NullableName", "nvarchar", 50, null, null, true, 3)
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Empty(errors);
}
[Fact]
public void ValidateBatch_DecimalOverflow_ReturnsError()
{
// Arrange
var data = new List<TestEntity>
{
new() { Id = 1, Name = "Test", Amount = 12345678.90m } // Too many integer digits for decimal(8,2)
};
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1),
new("Name", "nvarchar", 50, null, null, false, 2),
new("Amount", "decimal", null, 8, 2, false, 3) // Max 6 integer digits
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Single(errors);
Assert.Equal("Amount", errors[0].ColumnName);
Assert.Contains("exceeds maximum integer digits", errors[0].Message);
}
[Fact]
public void ValidateBatch_DecimalWithinRange_NoError()
{
// Arrange
var data = new List<TestEntity>
{
new() { Id = 1, Name = "Test", Amount = 123456.78m } // Within decimal(10,2) - 8 integer digits
};
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1),
new("Name", "nvarchar", 50, null, null, false, 2),
new("Amount", "decimal", null, 10, 2, false, 3) // Max 8 integer digits
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Empty(errors);
}
[Fact]
public void ValidateBatch_MultipleErrors_ReturnsAll()
{
// Arrange
var data = new List<TestEntity>
{
new() { Id = 1, Name = "This is too long" },
new() { Id = 2, Name = "Also too long!" }
};
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1),
new("Name", "nvarchar", 5, null, null, false, 2)
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Equal(2, errors.Count);
Assert.Equal(0, errors[0].RowIndex);
Assert.Equal(1, errors[1].RowIndex);
}
[Fact]
public void ValidateBatch_MaxErrors_StopsAtLimit()
{
// Arrange
var data = Enumerable.Range(0, 10)
.Select(i => new TestEntity { Id = i, Name = "This is way too long" })
.ToList();
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1),
new("Name", "nvarchar", 5, null, null, false, 2)
};
// Act
var errors = _validator.ValidateBatch(data, schema, maxErrors: 3);
// Assert
Assert.Equal(3, errors.Count);
}
[Fact]
public void ValidateBatch_UnmatchedColumn_Ignored()
{
// Arrange
var data = new List<TestEntity>
{
new() { Id = 1, Name = "Test" }
};
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1),
new("Name", "nvarchar", 50, null, null, false, 2),
new("UnknownColumn", "nvarchar", 50, null, null, false, 3)
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert
Assert.Empty(errors);
}
[Fact]
public void ValidateBatch_IdColumn_AllowsNull()
{
// Arrange - Id columns are treated as identity/auto-generated
var data = new List<TestEntity>
{
new() { Id = 0, Name = "Test" } // Id = 0 might be treated as "not set"
};
var schema = new List<ColumnSchema>
{
new("Id", "int", null, 10, 0, false, 1), // Not nullable in schema
new("Name", "nvarchar", 50, null, null, false, 2)
};
// Act
var errors = _validator.ValidateBatch(data, schema);
// Assert - No error because Id columns are treated specially
Assert.Empty(errors);
}
#endregion
}