8734c57c9b
Tests cover: - Capture group substitution in replacement - Case-insensitive matching - Null/DBNull passthrough - Non-target columns unchanged - Invalid regex pattern handling - Column not found handling
266 lines
7.7 KiB
C#
266 lines
7.7 KiB
C#
using System.Data;
|
|
using System.Text.RegularExpressions;
|
|
using JdeScoping.DataSync.Etl.Transformers;
|
|
using NSubstitute;
|
|
|
|
namespace JdeScoping.DataSync.Tests.Etl.Transformers;
|
|
|
|
public class RegexTransformerTests
|
|
{
|
|
[Fact]
|
|
public void FindReplace_RemovesPrefix()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "BatchID", "Name" },
|
|
values: new object[] { "IIS_12345", "Test" });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "BatchID",
|
|
pattern: "^IIS_",
|
|
replacement: "");
|
|
|
|
// Act
|
|
var reader = transformer.Transform(source);
|
|
source.Read().Returns(true);
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.Equal("12345", reader.GetValue(0));
|
|
Assert.Equal("Test", reader.GetValue(1)); // Other column unchanged
|
|
}
|
|
|
|
[Fact]
|
|
public void MatchExtract_ExtractsFirstCaptureGroup()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "Code" },
|
|
values: new object[] { "ID_12345" });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "Code",
|
|
pattern: @"ID_(\d+)",
|
|
replacement: null); // null = Match & Extract mode
|
|
|
|
// Act
|
|
var reader = transformer.Transform(source);
|
|
source.Read().Returns(true);
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.Equal("12345", reader.GetValue(0));
|
|
}
|
|
|
|
[Fact]
|
|
public void MatchExtract_NoMatch_KeepOriginal()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "Code" },
|
|
values: new object[] { "UNKNOWN" });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "Code",
|
|
pattern: @"ID_(\d+)",
|
|
replacement: null,
|
|
nonMatchBehavior: NonMatchBehavior.KeepOriginal);
|
|
|
|
// Act
|
|
var reader = transformer.Transform(source);
|
|
source.Read().Returns(true);
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.Equal("UNKNOWN", reader.GetValue(0));
|
|
}
|
|
|
|
[Fact]
|
|
public void MatchExtract_NoMatch_ReturnNull()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "Code" },
|
|
values: new object[] { "UNKNOWN" });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "Code",
|
|
pattern: @"ID_(\d+)",
|
|
replacement: null,
|
|
nonMatchBehavior: NonMatchBehavior.ReturnNull);
|
|
|
|
// Act
|
|
var reader = transformer.Transform(source);
|
|
source.Read().Returns(true);
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.Equal(DBNull.Value, reader.GetValue(0));
|
|
}
|
|
|
|
[Fact]
|
|
public void MatchExtract_NoMatch_ReturnEmpty()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "Code" },
|
|
values: new object[] { "UNKNOWN" });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "Code",
|
|
pattern: @"ID_(\d+)",
|
|
replacement: null,
|
|
nonMatchBehavior: NonMatchBehavior.ReturnEmpty);
|
|
|
|
// Act
|
|
var reader = transformer.Transform(source);
|
|
source.Read().Returns(true);
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.Equal(string.Empty, reader.GetValue(0));
|
|
}
|
|
|
|
[Fact]
|
|
public void FindReplace_UseCaptureGroups()
|
|
{
|
|
// Arrange - swap two numbers
|
|
var source = CreateMockReader(
|
|
columns: new[] { "Value" },
|
|
values: new object[] { "123-456" });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "Value",
|
|
pattern: @"(\d+)-(\d+)",
|
|
replacement: "$2-$1");
|
|
|
|
// Act
|
|
var reader = transformer.Transform(source);
|
|
source.Read().Returns(true);
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.Equal("456-123", reader.GetValue(0));
|
|
}
|
|
|
|
[Fact]
|
|
public void IgnoreCase_MatchesDifferentCase()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "BatchID" },
|
|
values: new object[] { "IIS_12345" });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "BatchID",
|
|
pattern: "^iis_", // lowercase pattern
|
|
replacement: "",
|
|
ignoreCase: true);
|
|
|
|
// Act
|
|
var reader = transformer.Transform(source);
|
|
source.Read().Returns(true);
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.Equal("12345", reader.GetValue(0));
|
|
}
|
|
|
|
[Fact]
|
|
public void NullValue_PassesThrough()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "BatchID" },
|
|
values: new object[] { DBNull.Value });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "BatchID",
|
|
pattern: "^IIS_",
|
|
replacement: "");
|
|
|
|
// Act
|
|
var reader = transformer.Transform(source);
|
|
source.Read().Returns(true);
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.Equal(DBNull.Value, reader.GetValue(0));
|
|
}
|
|
|
|
[Fact]
|
|
public void NonTargetColumn_Unchanged()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "BatchID", "OtherColumn" },
|
|
values: new object[] { "IIS_12345", "IIS_Should_Not_Change" });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "BatchID",
|
|
pattern: "^IIS_",
|
|
replacement: "");
|
|
|
|
// Act
|
|
var reader = transformer.Transform(source);
|
|
source.Read().Returns(true);
|
|
reader.Read();
|
|
|
|
// Assert
|
|
Assert.Equal("12345", reader.GetValue(0));
|
|
Assert.Equal("IIS_Should_Not_Change", reader.GetValue(1));
|
|
}
|
|
|
|
[Fact]
|
|
public void InvalidRegex_ThrowsOnTransform()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "Value" },
|
|
values: new object[] { "test" });
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "Value",
|
|
pattern: "[invalid(regex",
|
|
replacement: "");
|
|
|
|
// Act & Assert
|
|
var ex = Assert.Throws<RegexParseException>(() => transformer.Transform(source));
|
|
Assert.Contains("Invalid", ex.Message, StringComparison.OrdinalIgnoreCase);
|
|
}
|
|
|
|
[Fact]
|
|
public void ColumnNotFound_ThrowsOnTransform()
|
|
{
|
|
// Arrange
|
|
var source = CreateMockReader(
|
|
columns: new[] { "Value" },
|
|
values: new object[] { "test" });
|
|
source.GetOrdinal("NonExistent").Returns(_ => throw new IndexOutOfRangeException("Column not found"));
|
|
|
|
var transformer = new RegexTransformer(
|
|
columnName: "NonExistent",
|
|
pattern: "test",
|
|
replacement: "");
|
|
|
|
// Act & Assert
|
|
Assert.Throws<IndexOutOfRangeException>(() => transformer.Transform(source));
|
|
}
|
|
|
|
private static IDataReader CreateMockReader(string[] columns, object[] values)
|
|
{
|
|
var reader = Substitute.For<IDataReader>();
|
|
reader.FieldCount.Returns(columns.Length);
|
|
for (int i = 0; i < columns.Length; i++)
|
|
{
|
|
var index = i;
|
|
reader.GetName(index).Returns(columns[index]);
|
|
reader.GetOrdinal(columns[index]).Returns(index);
|
|
reader.GetFieldType(index).Returns(values[index]?.GetType() ?? typeof(object));
|
|
reader.GetValue(index).Returns(values[index]);
|
|
reader.IsDBNull(index).Returns(values[index] == null || values[index] == DBNull.Value);
|
|
}
|
|
return reader;
|
|
}
|
|
}
|