1e23616638
Replace FluentAssertions with Shouldly across all 6 test files (94 tests). Add ShouldlyExtensions for BeCloseTo and BeEquivalentTo patterns.
515 lines
21 KiB
C#
515 lines
21 KiB
C#
using Dapper;
|
|
using JdeScoping.Core.Models.Search;
|
|
using JdeScoping.Core.ViewModels;
|
|
using JdeScoping.Database.Tests.Infrastructure;
|
|
using Shouldly;
|
|
|
|
namespace JdeScoping.Database.Tests.Functions;
|
|
|
|
/// <summary>
|
|
/// Tests for complex table extraction functions that return multi-column result sets.
|
|
/// These inline TVFs extract object arrays from Search.Criteria JSON:
|
|
/// - fn_GetSearchComponentLots: returns (LotNumber, ItemNumber)
|
|
/// - fn_GetSearchPartOperations: returns (ItemNumber, OperationNumber, MisNumber, MisRevision)
|
|
/// </summary>
|
|
[Collection("DatabaseTests")]
|
|
public class ComplexTableFunctionTests : DatabaseTestBase
|
|
{
|
|
#region fn_GetSearchComponentLots Tests
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_ValidArray_ReturnsAllRowsWithAllColumns()
|
|
{
|
|
// Arrange
|
|
var criteria = new SearchCriteria
|
|
{
|
|
ComponentLotNumbers =
|
|
[
|
|
new LotViewModel { LotNumber = "LOT001", ItemNumber = "ITEM001" },
|
|
new LotViewModel { LotNumber = "LOT002", ItemNumber = "ITEM002" },
|
|
new LotViewModel { LotNumber = "LOT003", ItemNumber = "ITEM003" }
|
|
]
|
|
};
|
|
var searchId = await InsertTestSearchAsync(criteria);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string LotNumber, string ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(3);
|
|
resultList.ShouldContain(x => x.LotNumber == "LOT001" && x.ItemNumber == "ITEM001");
|
|
resultList.ShouldContain(x => x.LotNumber == "LOT002" && x.ItemNumber == "ITEM002");
|
|
resultList.ShouldContain(x => x.LotNumber == "LOT003" && x.ItemNumber == "ITEM003");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_EmptyArray_ReturnsEmpty()
|
|
{
|
|
// Arrange
|
|
var criteria = new SearchCriteria { ComponentLotNumbers = [] };
|
|
var searchId = await InsertTestSearchAsync(criteria);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string LotNumber, string ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_MissingProperty_ReturnsEmpty()
|
|
{
|
|
// Arrange - criteria without ComponentLotNumbers property
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync("{\"MinimumDt\":null}");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string LotNumber, string ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_SearchNotFound_ReturnsEmpty()
|
|
{
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string LotNumber, string ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = 99999 });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_NullCriteria_ReturnsEmpty()
|
|
{
|
|
// Arrange
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync(null);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string LotNumber, string ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_InvalidJson_ReturnsEmpty()
|
|
{
|
|
// Arrange
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync("not valid json");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string LotNumber, string ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_PartialObjects_UsesNullForMissingColumns()
|
|
{
|
|
// Arrange - JSON with objects missing some properties
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync(
|
|
"{\"ComponentLotNumbers\":[" +
|
|
"{\"LotNumber\":\"LOT001\"}," + // Missing ItemNumber
|
|
"{\"ItemNumber\":\"ITEM002\"}," + // Missing LotNumber
|
|
"{\"LotNumber\":\"LOT003\",\"ItemNumber\":\"ITEM003\"}" + // Complete
|
|
"]}");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string? LotNumber, string? ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(3);
|
|
resultList.ShouldContain(x => x.LotNumber == "LOT001" && x.ItemNumber == null);
|
|
resultList.ShouldContain(x => x.LotNumber == null && x.ItemNumber == "ITEM002");
|
|
resultList.ShouldContain(x => x.LotNumber == "LOT003" && x.ItemNumber == "ITEM003");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_SpecialCharacters_ReturnsCorrectly()
|
|
{
|
|
// Arrange
|
|
var criteria = new SearchCriteria
|
|
{
|
|
ComponentLotNumbers =
|
|
[
|
|
new LotViewModel { LotNumber = "LOT-001", ItemNumber = "ITEM_001" },
|
|
new LotViewModel { LotNumber = "LOT.002", ItemNumber = "ITEM/002" }
|
|
]
|
|
};
|
|
var searchId = await InsertTestSearchAsync(criteria);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string LotNumber, string ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(2);
|
|
resultList.ShouldContain(x => x.LotNumber == "LOT-001" && x.ItemNumber == "ITEM_001");
|
|
resultList.ShouldContain(x => x.LotNumber == "LOT.002" && x.ItemNumber == "ITEM/002");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region fn_GetSearchPartOperations Tests
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_ValidArray_ReturnsAllRowsWithAllColumns()
|
|
{
|
|
// Arrange
|
|
var criteria = new SearchCriteria
|
|
{
|
|
PartOperations =
|
|
[
|
|
new PartOperationViewModel
|
|
{
|
|
ItemNumber = "ITEM001",
|
|
OperationNumber = "10",
|
|
MisNumber = "MIS001",
|
|
MisRevision = "A"
|
|
},
|
|
new PartOperationViewModel
|
|
{
|
|
ItemNumber = "ITEM002",
|
|
OperationNumber = "20",
|
|
MisNumber = "MIS002",
|
|
MisRevision = "B"
|
|
},
|
|
new PartOperationViewModel
|
|
{
|
|
ItemNumber = "ITEM003",
|
|
OperationNumber = "30",
|
|
MisNumber = "MIS003",
|
|
MisRevision = "C"
|
|
}
|
|
]
|
|
};
|
|
var searchId = await InsertTestSearchAsync(criteria);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string ItemNumber, string OperationNumber, string MisNumber, string MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(3);
|
|
resultList.ShouldContain(x => x.ItemNumber == "ITEM001" && x.OperationNumber == "10" && x.MisNumber == "MIS001" && x.MisRevision == "A");
|
|
resultList.ShouldContain(x => x.ItemNumber == "ITEM002" && x.OperationNumber == "20" && x.MisNumber == "MIS002" && x.MisRevision == "B");
|
|
resultList.ShouldContain(x => x.ItemNumber == "ITEM003" && x.OperationNumber == "30" && x.MisNumber == "MIS003" && x.MisRevision == "C");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_EmptyArray_ReturnsEmpty()
|
|
{
|
|
// Arrange
|
|
var criteria = new SearchCriteria { PartOperations = [] };
|
|
var searchId = await InsertTestSearchAsync(criteria);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string ItemNumber, string OperationNumber, string MisNumber, string MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_MissingProperty_ReturnsEmpty()
|
|
{
|
|
// Arrange - criteria without PartOperations property
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync("{\"MinimumDt\":null}");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string ItemNumber, string OperationNumber, string MisNumber, string MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_SearchNotFound_ReturnsEmpty()
|
|
{
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string ItemNumber, string OperationNumber, string MisNumber, string MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = 99999 });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_NullCriteria_ReturnsEmpty()
|
|
{
|
|
// Arrange
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync(null);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string ItemNumber, string OperationNumber, string MisNumber, string MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_InvalidJson_ReturnsEmpty()
|
|
{
|
|
// Arrange
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync("not valid json");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string ItemNumber, string OperationNumber, string MisNumber, string MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.ShouldBeEmpty();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_PartialObjects_UsesNullForMissingColumns()
|
|
{
|
|
// Arrange - JSON with objects missing some properties
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync(
|
|
"{\"PartOperations\":[" +
|
|
"{\"ItemNumber\":\"ITEM001\",\"OperationNumber\":\"10\"}," + // Missing MisNumber and MisRevision
|
|
"{\"MisNumber\":\"MIS002\",\"MisRevision\":\"B\"}," + // Missing ItemNumber and OperationNumber
|
|
"{\"ItemNumber\":\"ITEM003\",\"OperationNumber\":\"30\",\"MisNumber\":\"MIS003\",\"MisRevision\":\"C\"}" + // Complete
|
|
"]}");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string? ItemNumber, string? OperationNumber, string? MisNumber, string? MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(3);
|
|
resultList.ShouldContain(x => x.ItemNumber == "ITEM001" && x.OperationNumber == "10" && x.MisNumber == null && x.MisRevision == null);
|
|
resultList.ShouldContain(x => x.ItemNumber == null && x.OperationNumber == null && x.MisNumber == "MIS002" && x.MisRevision == "B");
|
|
resultList.ShouldContain(x => x.ItemNumber == "ITEM003" && x.OperationNumber == "30" && x.MisNumber == "MIS003" && x.MisRevision == "C");
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_NullOptionalFields_ReturnsWithNulls()
|
|
{
|
|
// Arrange - using C# model with empty strings (which serialize to "")
|
|
// The SQL function handles nulls/missing in JSON, so we test explicit null in JSON
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync(
|
|
"{\"PartOperations\":[" +
|
|
"{\"ItemNumber\":\"ITEM001\",\"OperationNumber\":\"10\",\"MisNumber\":null,\"MisRevision\":null}" +
|
|
"]}");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string? ItemNumber, string? OperationNumber, string? MisNumber, string? MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(1);
|
|
var result = resultList.First();
|
|
result.ItemNumber.ShouldBe("ITEM001");
|
|
result.OperationNumber.ShouldBe("10");
|
|
result.MisNumber.ShouldBeNull();
|
|
result.MisRevision.ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_SpecialCharacters_ReturnsCorrectly()
|
|
{
|
|
// Arrange
|
|
var criteria = new SearchCriteria
|
|
{
|
|
PartOperations =
|
|
[
|
|
new PartOperationViewModel
|
|
{
|
|
ItemNumber = "ITEM-001",
|
|
OperationNumber = "10A",
|
|
MisNumber = "MIS.001",
|
|
MisRevision = "A-1"
|
|
}
|
|
]
|
|
};
|
|
var searchId = await InsertTestSearchAsync(criteria);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string ItemNumber, string OperationNumber, string MisNumber, string MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(1);
|
|
var result = resultList.First();
|
|
result.ItemNumber.ShouldBe("ITEM-001");
|
|
result.OperationNumber.ShouldBe("10A");
|
|
result.MisNumber.ShouldBe("MIS.001");
|
|
result.MisRevision.ShouldBe("A-1");
|
|
}
|
|
|
|
#endregion
|
|
|
|
#region Additional Edge Case Tests
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_LargeArray_ReturnsAll()
|
|
{
|
|
// Arrange
|
|
var lots = Enumerable.Range(1, 100)
|
|
.Select(i => new LotViewModel { LotNumber = $"LOT{i:D4}", ItemNumber = $"ITEM{i:D4}" })
|
|
.ToList();
|
|
var criteria = new SearchCriteria { ComponentLotNumbers = lots };
|
|
var searchId = await InsertTestSearchAsync(criteria);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string LotNumber, string ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.Count().ShouldBe(100);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_LargeArray_ReturnsAll()
|
|
{
|
|
// Arrange
|
|
var operations = Enumerable.Range(1, 100)
|
|
.Select(i => new PartOperationViewModel
|
|
{
|
|
ItemNumber = $"ITEM{i:D4}",
|
|
OperationNumber = $"{i * 10}",
|
|
MisNumber = $"MIS{i:D4}",
|
|
MisRevision = $"R{i}"
|
|
})
|
|
.ToList();
|
|
var criteria = new SearchCriteria { PartOperations = operations };
|
|
var searchId = await InsertTestSearchAsync(criteria);
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string ItemNumber, string OperationNumber, string MisNumber, string MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
results.Count().ShouldBe(100);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_EmptyObject_ReturnsRowWithNulls()
|
|
{
|
|
// Arrange - JSON with empty object in array
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync(
|
|
"{\"ComponentLotNumbers\":[{}]}");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string? LotNumber, string? ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(1);
|
|
resultList.First().LotNumber.ShouldBeNull();
|
|
resultList.First().ItemNumber.ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_EmptyObject_ReturnsRowWithNulls()
|
|
{
|
|
// Arrange - JSON with empty object in array
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync(
|
|
"{\"PartOperations\":[{}]}");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string? ItemNumber, string? OperationNumber, string? MisNumber, string? MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(1);
|
|
var result = resultList.First();
|
|
result.ItemNumber.ShouldBeNull();
|
|
result.OperationNumber.ShouldBeNull();
|
|
result.MisNumber.ShouldBeNull();
|
|
result.MisRevision.ShouldBeNull();
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchComponentLots_LongValues_Truncated()
|
|
{
|
|
// Arrange - LotNumber is VARCHAR(30), ItemNumber is VARCHAR(128)
|
|
var longLotNumber = new string('L', 50); // Will be truncated to 30
|
|
var longItemNumber = new string('I', 200); // Will be truncated to 128
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync(
|
|
$"{{\"ComponentLotNumbers\":[{{\"LotNumber\":\"{longLotNumber}\",\"ItemNumber\":\"{longItemNumber}\"}}]}}");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string LotNumber, string ItemNumber)>(
|
|
"SELECT LotNumber, ItemNumber FROM dbo.fn_GetSearchComponentLots(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(1);
|
|
resultList.First().LotNumber.Length.ShouldBe(30);
|
|
resultList.First().ItemNumber.Length.ShouldBe(128);
|
|
}
|
|
|
|
[Fact]
|
|
public async Task fn_GetSearchPartOperations_LongValues_Truncated()
|
|
{
|
|
// Arrange - ItemNumber VARCHAR(128), OperationNumber/MisNumber/MisRevision VARCHAR(10)
|
|
var longItemNumber = new string('I', 200); // Truncated to 128
|
|
var longOperationNumber = new string('O', 20); // Truncated to 10
|
|
var longMisNumber = new string('M', 20); // Truncated to 10
|
|
var longMisRevision = new string('R', 20); // Truncated to 10
|
|
var searchId = await InsertTestSearchWithRawCriteriaAsync(
|
|
$"{{\"PartOperations\":[{{\"ItemNumber\":\"{longItemNumber}\",\"OperationNumber\":\"{longOperationNumber}\",\"MisNumber\":\"{longMisNumber}\",\"MisRevision\":\"{longMisRevision}\"}}]}}");
|
|
|
|
// Act
|
|
var results = await Connection.QueryAsync<(string ItemNumber, string OperationNumber, string MisNumber, string MisRevision)>(
|
|
"SELECT ItemNumber, OperationNumber, MisNumber, MisRevision FROM dbo.fn_GetSearchPartOperations(@SearchId)",
|
|
new { SearchId = searchId });
|
|
|
|
// Assert
|
|
var resultList = results.ToList();
|
|
resultList.Count.ShouldBe(1);
|
|
var result = resultList.First();
|
|
result.ItemNumber.Length.ShouldBe(128);
|
|
result.OperationNumber.Length.ShouldBe(10);
|
|
result.MisNumber.Length.ShouldBe(10);
|
|
result.MisRevision.Length.ShouldBe(10);
|
|
}
|
|
|
|
#endregion
|
|
}
|