using Strata.SqlTools.Interfaces; using System.Linq; using System.Text; namespace Strata.SqlTools.SqlBreakdown.Tests; /// /// Unit tests for the SqlBreakdownCollection class. /// [TestFixture] public class SqlBreakdownCollectionTests { [Test] public void Constructor_WithNoArguments_CreatesEmptyCollection() { // Arrange & Act var collection = new SqlBreakdownCollection(); // Assert Assert.That(collection.Count, Is.EqualTo(0)); Assert.That(collection.IsEmpty, Is.True); Assert.That(collection.Breakdowns, Is.Empty); Assert.That(collection.RawStatements, Is.Empty); } [Test] public void Constructor_WithBreakdownList_InitializesCollection() { // Arrange var mockBreakdowns = new List { new MockSqlBreakdown("SELECT * FROM Table1"), new MockSqlBreakdown("SELECT * FROM Table2") }; // Act var collection = new SqlBreakdownCollection(mockBreakdowns); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.IsEmpty, Is.False); } [Test] public void Add_WithValidBreakdown_AddsToCollection() { // Arrange var collection = new SqlBreakdownCollection(); var breakdown = new MockSqlBreakdown("SELECT * FROM Table1"); // Act collection.Add(breakdown); // Assert Assert.That(collection.Count, Is.EqualTo(1)); Assert.That(collection.GetAt(0), Is.EqualTo(breakdown)); } [Test] public void Add_WithNullBreakdown_ThrowsArgumentNullException() { // Arrange var collection = new SqlBreakdownCollection(); // Act & Assert Assert.Throws(() => collection.Add(null!)); } [Test] public void AddRange_WithMultipleBreakdowns_AddsAllItems() { // Arrange var collection = new SqlBreakdownCollection(); var breakdowns = new List { new MockSqlBreakdown("SELECT * FROM Table1"), new MockSqlBreakdown("SELECT * FROM Table2"), new MockSqlBreakdown("SELECT * FROM Table3") }; // Act collection.AddRange(breakdowns); // Assert Assert.That(collection.Count, Is.EqualTo(3)); } [Test] public void AddRange_WithNullCollection_ThrowsArgumentNullException() { // Arrange var collection = new SqlBreakdownCollection(); // Act & Assert Assert.Throws(() => collection.AddRange(null!)); } [Test] public void Remove_WithExistingBreakdown_RemovesItem() { // Arrange var breakdown = new MockSqlBreakdown("SELECT * FROM Table1"); var collection = new SqlBreakdownCollection(new[] { breakdown }); // Act var result = collection.Remove(breakdown); // Assert Assert.That(result, Is.True); Assert.That(collection.Count, Is.EqualTo(0)); } [Test] public void Remove_WithNonExistingBreakdown_ReturnsFalse() { // Arrange var collection = new SqlBreakdownCollection(new[] { new MockSqlBreakdown("SELECT * FROM Table1") }); var otherBreakdown = new MockSqlBreakdown("SELECT * FROM Table2"); // Act var result = collection.Remove(otherBreakdown); // Assert Assert.That(result, Is.False); Assert.That(collection.Count, Is.EqualTo(1)); } [Test] public void Clear_WithMultipleItems_RemovesAll() { // Arrange var collection = new SqlBreakdownCollection(new[] { new MockSqlBreakdown("SELECT * FROM Table1"), new MockSqlBreakdown("SELECT * FROM Table2") }); // Act collection.Clear(); // Assert Assert.That(collection.Count, Is.EqualTo(0)); Assert.That(collection.IsEmpty, Is.True); } [Test] public void ParseBatch_WithGoSeparators_ParsesStatements() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" SELECT * FROM Table1 GO SELECT * FROM Table2 GO SELECT * FROM Table3 "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.RawStatements.Count, Is.EqualTo(3)); Assert.That(collection.RawStatements[0], Does.Contain("Table1")); Assert.That(collection.RawStatements[1], Does.Contain("Table2")); Assert.That(collection.RawStatements[2], Does.Contain("Table3")); } [Test] public void ParseBatch_WithMixedCaseGO_ParsesCorrectly() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" SELECT * FROM Table1 go SELECT * FROM Table2 GO SELECT * FROM Table3 "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.RawStatements.Count, Is.EqualTo(3)); } [Test] public void ParseBatch_WithGoAndWhitespace_ParsesCorrectly() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" SELECT * FROM Table1 GO SELECT * FROM Table2 GO SELECT * FROM Table3 "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.RawStatements.Count, Is.EqualTo(3)); } [Test] public void ParseBatch_WithEmptyStatements_FiltersOutEmptyValues() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" SELECT * FROM Table1 GO GO SELECT * FROM Table2 "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.RawStatements.Count, Is.EqualTo(2)); Assert.That(collection.RawStatements[0], Does.Contain("Table1")); Assert.That(collection.RawStatements[1], Does.Contain("Table2")); } [Test] public void ParseBatch_WithNullInput_ThrowsArgumentNullException() { // Arrange var collection = new SqlBreakdownCollection(); // Act & Assert Assert.Throws(() => collection.ParseBatch(null!)); } [Test] public void GetCombinedSql_WithMultipleBreakdowns_CombinesSqlWithSeparator() { // Arrange var breakdowns = new[] { new MockSqlBreakdown("SELECT * FROM Table1"), new MockSqlBreakdown("SELECT * FROM Table2") }; var collection = new SqlBreakdownCollection(breakdowns); // Act var result = collection.GetCombinedSql(); // Assert Assert.That(result, Does.Contain("Table1")); Assert.That(result, Does.Contain("Table2")); Assert.That(result, Does.Contain("GO")); } [Test] public void GetCombinedSql_WithEmptyCollection_ReturnsEmpty() { // Arrange var collection = new SqlBreakdownCollection(); // Act var result = collection.GetCombinedSql(); // Assert Assert.That(result, Is.Empty); } [Test] public void GetCombinedSql_WithCustomSeparator_UsesCustomSeparator() { // Arrange var breakdowns = new[] { new MockSqlBreakdown("SELECT * FROM Table1"), new MockSqlBreakdown("SELECT * FROM Table2") }; var collection = new SqlBreakdownCollection(breakdowns); // Act var result = collection.GetCombinedSql(true, ";"); // Assert Assert.That(result, Does.Contain(";")); Assert.That(result, Does.Not.Contain("GO")); } [Test] public void GetBatchSql_WithRawStatements_CombinesWithGO() { // Arrange var collection = new SqlBreakdownCollection(); collection.ParseBatch(@" SELECT * FROM Table1 GO SELECT * FROM Table2 "); // Act var result = collection.GetBatchSql(); // Assert Assert.That(result, Does.Contain("Table1")); Assert.That(result, Does.Contain("GO")); Assert.That(result, Does.Contain("Table2")); } [Test] public void GetBatchSql_WithEmptyCollection_ReturnsEmpty() { // Arrange var collection = new SqlBreakdownCollection(); // Act var result = collection.GetBatchSql(); // Assert Assert.That(result, Is.Empty); } [Test] public void Where_WithValidPredicate_FiltersBreakdowns() { // Arrange var breakdowns = new[] { new MockSqlBreakdown("SELECT * FROM Table1"), new MockSqlBreakdown("SELECT * FROM Table2"), new MockSqlBreakdown("SELECT * FROM Table3") }; var collection = new SqlBreakdownCollection(breakdowns); // Act var filtered = collection.Where(b => b.ToString()!.Contains("Table2")).ToList(); // Assert Assert.That(filtered.Count, Is.EqualTo(1)); Assert.That(filtered[0].ToString()!, Does.Contain("Table2")); } [Test] public void Select_WithValidSelector_ProjectsBreakdowns() { // Arrange var breakdowns = new[] { new MockSqlBreakdown("SELECT * FROM Table1"), new MockSqlBreakdown("SELECT * FROM Table2") }; var collection = new SqlBreakdownCollection(breakdowns); // Act var projected = collection.Select(b => b.ToString()!.Length).ToList(); // Assert Assert.That(projected.Count, Is.EqualTo(2)); Assert.That(projected[0], Is.GreaterThan(0)); } [Test] public void GetAt_WithValidIndex_ReturnsBreakdown() { // Arrange var breakdown1 = new MockSqlBreakdown("SELECT * FROM Table1"); var breakdown2 = new MockSqlBreakdown("SELECT * FROM Table2"); var collection = new SqlBreakdownCollection(new[] { breakdown1, breakdown2 }); // Act var result = collection.GetAt(1); // Assert Assert.That(result, Is.EqualTo(breakdown2)); } [Test] public void GetAt_WithInvalidIndex_ThrowsIndexOutOfRangeException() { // Arrange var collection = new SqlBreakdownCollection(new[] { new MockSqlBreakdown("SELECT * FROM Table1") }); // Act & Assert Assert.Throws(() => collection.GetAt(5)); } [Test] public void FirstOrDefault_WithMatchingPredicate_ReturnsBreakdown() { // Arrange var breakdowns = new[] { new MockSqlBreakdown("SELECT * FROM Table1"), new MockSqlBreakdown("SELECT * FROM Table2") }; var collection = new SqlBreakdownCollection(breakdowns); // Act var result = collection.FirstOrDefault(b => b.ToString()!.Contains("Table2")); // Assert Assert.That(result, Is.Not.Null); Assert.That(result!.ToString(), Does.Contain("Table2")); } [Test] public void FirstOrDefault_WithNoMatch_ReturnsNull() { // Arrange var collection = new SqlBreakdownCollection(new[] { new MockSqlBreakdown("SELECT * FROM Table1") }); // Act var result = collection.FirstOrDefault(b => b.ToString()!.Contains("NonExistent")); // Assert Assert.That(result, Is.Null); } [Test] public void GetRawStatementAt_WithValidIndex_ReturnsStatement() { // Arrange var collection = new SqlBreakdownCollection(); collection.ParseBatch(@" SELECT * FROM Table1 GO SELECT * FROM Table2 "); // Act var result = collection.GetRawStatementAt(1); // Assert Assert.That(result, Does.Contain("Table2")); } [Test] public void GetRawStatementAt_WithInvalidIndex_ThrowsIndexOutOfRangeException() { // Arrange var collection = new SqlBreakdownCollection(); collection.ParseBatch("SELECT * FROM Table1"); // Act & Assert Assert.Throws(() => collection.GetRawStatementAt(5)); } [Test] public void ToString_ReturnsFormattedSql() { // Arrange var breakdowns = new[] { new MockSqlBreakdown("SELECT * FROM Table1"), new MockSqlBreakdown("SELECT * FROM Table2") }; var collection = new SqlBreakdownCollection(breakdowns); // Act var result = collection.ToString(); // Assert Assert.That(result, Does.Contain("Table1")); Assert.That(result, Does.Contain("Table2")); Assert.That(result, Does.Contain("GO")); } // ============================================================ // CRUD Tests - Complete SQL Statement Coverage // ============================================================ #region CREATE Tests [Test] public void ParseBatch_WithCreateTableStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" CREATE TABLE Users ( Id INT PRIMARY KEY, Name NVARCHAR(100), Email NVARCHAR(100) ) GO CREATE TABLE Orders ( OrderId INT PRIMARY KEY, UserId INT FOREIGN KEY REFERENCES Users(Id), OrderDate DATETIME ) "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("CREATE TABLE Users")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("CREATE TABLE Orders")); } [Test] public void ParseBatch_WithCreateIndexStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" CREATE INDEX idx_Users_Email ON Users(Email) GO CREATE UNIQUE INDEX idx_Orders_OrderDate ON Orders(OrderDate) "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("CREATE INDEX")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("UNIQUE")); } [Test] public void ParseBatch_WithCreateProcedureStatement_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" CREATE PROCEDURE sp_GetUserById @UserId INT AS BEGIN SELECT * FROM Users WHERE Id = @UserId END "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.GreaterThanOrEqualTo(1)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("CREATE PROCEDURE")); } #endregion #region INSERT (CREATE Data) Tests [Test] public void ParseBatch_WithInsertStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" INSERT INTO Users (Id, Name, Email) VALUES (1, 'John Doe', 'john@example.com') GO INSERT INTO Users (Id, Name, Email) VALUES (2, 'Jane Smith', 'jane@example.com') GO INSERT INTO Users (Id, Name, Email) VALUES (3, 'Bob Johnson', 'bob@example.com') "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(3)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("INSERT INTO Users")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("Jane Smith")); Assert.That(collection.GetRawStatementAt(2), Does.Contain("Bob Johnson")); } [Test] public void ParseBatch_WithInsertSelectStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" INSERT INTO UsersArchive SELECT Id, Name, Email FROM Users WHERE CreatedDate < '2020-01-01' GO INSERT INTO OrdersBackup SELECT OrderId, UserId, OrderDate FROM Orders WHERE OrderDate < DATEADD(year, -1, GETDATE()) "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("INSERT INTO UsersArchive")); Assert.That(collection.GetRawStatementAt(0), Does.Contain("SELECT")); } [Test] public void ParseBatch_WithBulkInsertStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" BULK INSERT Users FROM 'C:\data\users.csv' WITH (FIELDTERMINATOR=',', ROWTERMINATOR='\n') GO BULK INSERT Orders FROM 'C:\data\orders.csv' WITH (FIELDTERMINATOR=',', ROWTERMINATOR='\n') "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("BULK INSERT")); } #endregion #region SELECT (READ) Tests [Test] public void ParseBatch_WithComplexSelectStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" SELECT u.Id, u.Name, COUNT(o.OrderId) AS OrderCount FROM Users u LEFT JOIN Orders o ON u.Id = o.UserId WHERE u.CreatedDate > '2020-01-01' GROUP BY u.Id, u.Name HAVING COUNT(o.OrderId) > 0 ORDER BY OrderCount DESC GO SELECT * FROM Orders WHERE OrderDate BETWEEN '2020-01-01' AND '2021-12-31' "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("LEFT JOIN")); Assert.That(collection.GetRawStatementAt(0), Does.Contain("GROUP BY")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("BETWEEN")); } [Test] public void ParseBatch_WithSelectWithCommonTableExpression_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" WITH UserOrders AS ( SELECT UserId, OrderId, OrderDate FROM Orders WHERE OrderDate > '2020-01-01' ) SELECT u.Id, u.Name, uo.OrderId FROM Users u INNER JOIN UserOrders uo ON u.Id = uo.UserId "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.GreaterThanOrEqualTo(1)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("WITH UserOrders AS")); } [Test] public void ParseBatch_WithSelectFromMultipleTables_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" SELECT u.Id, u.Name, o.OrderId, p.ProductName FROM Users u JOIN Orders o ON u.Id = o.UserId JOIN OrderItems oi ON o.OrderId = oi.OrderId JOIN Products p ON oi.ProductId = p.Id WHERE u.Country = 'USA' GO SELECT * FROM UserProfiles WHERE UserId IN (SELECT Id FROM Users) "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("JOIN")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("IN")); } #endregion #region UPDATE Tests [Test] public void ParseBatch_WithUpdateStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" UPDATE Users SET Name = 'John Updated', ModifiedDate = GETDATE() WHERE Id = 1 GO UPDATE Orders SET Status = 'Shipped' WHERE OrderDate < DATEADD(day, -30, GETDATE()) GO UPDATE Products SET Price = Price * 1.1 WHERE Category = 'Electronics' "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(3)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("UPDATE Users")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("Status")); Assert.That(collection.GetRawStatementAt(2), Does.Contain("Price * 1.1")); } [Test] public void ParseBatch_WithUpdateFromSelectStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" UPDATE u SET u.LastOrderDate = (SELECT MAX(OrderDate) FROM Orders WHERE UserId = u.Id) FROM Users u WHERE u.Id IN (SELECT DISTINCT UserId FROM Orders) GO UPDATE Products SET Quantity = Quantity - 1 FROM OrderItems oi WHERE Products.Id = oi.ProductId AND oi.OrderId = 100 "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("UPDATE u")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("Quantity - 1")); } [Test] public void ParseBatch_WithUpdateWithJoinStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" UPDATE Orders SET OrderStatus = 'Processed' FROM Orders o JOIN OrderItems oi ON o.OrderId = oi.OrderId WHERE oi.Quantity > 50 "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.GreaterThanOrEqualTo(1)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("UPDATE Orders")); Assert.That(collection.GetRawStatementAt(0), Does.Contain("JOIN")); } #endregion #region DELETE Tests [Test] public void ParseBatch_WithDeleteStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" DELETE FROM Orders WHERE OrderDate < '2019-01-01' GO DELETE FROM UserProfiles WHERE UserId NOT IN (SELECT Id FROM Users) GO DELETE FROM AuditLog WHERE LogDate < DATEADD(year, -2, GETDATE()) "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(3)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("DELETE FROM Orders")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("NOT IN")); Assert.That(collection.GetRawStatementAt(2), Does.Contain("DATEADD")); } [Test] public void ParseBatch_WithDeleteFromSelectStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" DELETE o FROM Orders o WHERE NOT EXISTS (SELECT 1 FROM OrderItems oi WHERE oi.OrderId = o.OrderId) GO DELETE FROM Users WHERE Id IN (SELECT UserId FROM Orders WHERE OrderStatus = 'Cancelled') "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("EXISTS")); } [Test] public void ParseBatch_WithDeleteWithJoinStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" DELETE Orders FROM Orders o INNER JOIN OrderStatuses os ON o.StatusId = os.Id WHERE os.StatusName = 'Archived' "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.GreaterThanOrEqualTo(1)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("DELETE Orders")); Assert.That(collection.GetRawStatementAt(0), Does.Contain("INNER JOIN")); } #endregion #region DROP Tests [Test] public void ParseBatch_WithDropTableStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" DROP TABLE IF EXISTS OrderItems GO DROP TABLE IF EXISTS Orders GO DROP TABLE IF EXISTS Users "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(3)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("DROP TABLE")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("DROP TABLE")); } [Test] public void ParseBatch_WithDropIndexAndProcedureStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" DROP INDEX IF EXISTS idx_Users_Email ON Users GO DROP PROCEDURE IF EXISTS sp_GetUserById GO DROP VIEW IF EXISTS vw_UserOrders "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(3)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("DROP INDEX")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("PROCEDURE")); Assert.That(collection.GetRawStatementAt(2), Does.Contain("VIEW")); } #endregion #region Mixed CRUD Operations Tests [Test] public void ParseBatch_WithMixedCrudOperations_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" CREATE TABLE Users ( Id INT PRIMARY KEY, Name NVARCHAR(100), Email NVARCHAR(100) ) GO INSERT INTO Users (Id, Name, Email) VALUES (1, 'John Doe', 'john@example.com') GO INSERT INTO Users (Id, Name, Email) VALUES (2, 'Jane Smith', 'jane@example.com') GO SELECT * FROM Users WHERE Id = 1 GO UPDATE Users SET Name = 'John Updated' WHERE Id = 1 GO DELETE FROM Users WHERE Id = 2 GO DROP TABLE Users "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(7)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("CREATE TABLE")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("INSERT")); Assert.That(collection.GetRawStatementAt(3), Does.Contain("SELECT")); Assert.That(collection.GetRawStatementAt(4), Does.Contain("UPDATE")); Assert.That(collection.GetRawStatementAt(5), Does.Contain("DELETE")); Assert.That(collection.GetRawStatementAt(6), Does.Contain("DROP")); } [Test] public void ParseBatch_WithComplexMultipleStatements_ParsesAllStatements() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" CREATE TABLE Products ( Id INT PRIMARY KEY, Name NVARCHAR(100), Price DECIMAL(10, 2), Quantity INT ) GO INSERT INTO Products (Id, Name, Price, Quantity) SELECT Id, ProductName, BasePrice, StockQuantity FROM StagingProducts WHERE IsActive = 1 GO UPDATE Products SET Price = Price * 1.1 WHERE Quantity < 10 GO SELECT p.Name, COUNT(oi.Id) AS OrderCount, SUM(oi.Quantity) AS TotalSold FROM Products p LEFT JOIN OrderItems oi ON p.Id = oi.ProductId GROUP BY p.Id, p.Name HAVING SUM(oi.Quantity) > 100 GO DELETE FROM Products WHERE Quantity = 0 AND LastUpdated < DATEADD(month, -6, GETDATE()) "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(5)); Assert.That(collection.RawStatements.Count, Is.EqualTo(5)); foreach (var statement in collection.RawStatements) { Assert.That(statement, Is.Not.Empty); } } #endregion #region Transaction Tests [Test] public void ParseBatch_WithTransactionStatements_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" BEGIN TRANSACTION UpdatePrices UPDATE Products SET Price = Price * 1.1 WHERE Category = 'Electronics' UPDATE ProductPriceHistory SET NewPrice = Price FROM Products WHERE Products.Id = ProductPriceHistory.ProductId COMMIT TRANSACTION UpdatePrices GO BEGIN TRANSACTION DeleteOldOrders DELETE FROM OrderItems WHERE OrderId IN (SELECT OrderId FROM Orders WHERE OrderDate < '2018-01-01') DELETE FROM Orders WHERE OrderDate < '2018-01-01' COMMIT TRANSACTION DeleteOldOrders "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.GreaterThanOrEqualTo(1)); var statement = collection.GetRawStatementAt(0); Assert.That(statement, Does.Contain("BEGIN TRANSACTION")); Assert.That(statement, Does.Contain("COMMIT")); } #endregion #region Custom Separator Tests [Test] public void ParseBatch_WithSemicolonSeparator_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" SELECT * FROM Users ; SELECT * FROM Orders ; SELECT * FROM Products "; // Act collection.ParseBatch(batchSql, ";"); // Assert Assert.That(collection.Count, Is.EqualTo(3)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("Users")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("Orders")); Assert.That(collection.GetRawStatementAt(2), Does.Contain("Products")); } [Test] public void ParseBatch_WithCustomSeparator_ParsesSuccessfully() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" INSERT INTO Users VALUES (1, 'John') ~~~ INSERT INTO Users VALUES (2, 'Jane') ~~~ INSERT INTO Users VALUES (3, 'Bob') "; // Act collection.ParseBatch(batchSql, "~~~"); // Assert Assert.That(collection.Count, Is.EqualTo(3)); Assert.That(collection.RawStatements.Count, Is.EqualTo(3)); } #endregion #region Parameter Tests with CRUD [Test] public void ParseBatch_WithParameterizedInsertStatements_PreservesParameters() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" INSERT INTO Users (Id, Name, Email) VALUES (@UserId, @UserName, @UserEmail) GO INSERT INTO Orders (OrderId, UserId, OrderDate) VALUES (@OrderId, @UserId, @OrderDate) "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("@UserId")); Assert.That(collection.GetRawStatementAt(0), Does.Contain("@UserEmail")); } [Test] public void ParseBatch_WithParameterizedUpdateStatements_PreservesParameters() { // Arrange var collection = new SqlBreakdownCollection(); var batchSql = @" UPDATE Users SET Name = @Name, Email = @Email WHERE Id = @UserId GO UPDATE Orders SET Status = @Status, ModifiedDate = @ModifiedDate WHERE OrderId = @OrderId "; // Act collection.ParseBatch(batchSql); // Assert Assert.That(collection.Count, Is.EqualTo(2)); Assert.That(collection.GetRawStatementAt(0), Does.Contain("@Name")); Assert.That(collection.GetRawStatementAt(1), Does.Contain("@Status")); } [Test] public void GetCombinedSql_WithMixedCrudOperations_CombinesCorrectly() { // Arrange var collection = new SqlBreakdownCollection(); collection.ParseBatch(@" INSERT INTO Users (Id, Name) VALUES (1, 'John') GO UPDATE Users SET Name = 'Jane' WHERE Id = 1 GO DELETE FROM Users WHERE Id = 1 "); // Act var combined = collection.GetCombinedSql(); // Assert Assert.That(combined, Does.Contain("INSERT")); Assert.That(combined, Does.Contain("UPDATE")); Assert.That(combined, Does.Contain("DELETE")); Assert.That(combined, Does.Contain("GO")); } #endregion /// /// Mock implementation of ISqlBreakdown for testing purposes. /// public class MockSqlBreakdown : ISqlBreakdown { private readonly string _sql; public MockSqlBreakdown(string sql) { _sql = sql; SetupClauses = new List(); FinishClauses = new System.Collections.ArrayList(); } public string? RawSql { get; set; } public List SetupClauses { get; set; } public bool IsUsingSetupClause => SetupClauses.Count > 0; public System.Collections.ArrayList FinishClauses { get; set; } public bool IsUsingFinishClause => FinishClauses.Count > 0; public string GetSql(bool includeSetupFinish = true) { var sb = new StringBuilder(); if (includeSetupFinish) { foreach (string setup in SetupClauses) { sb.AppendLine(setup); } } sb.Append(_sql); if (includeSetupFinish) { foreach (string finish in FinishClauses) { sb.AppendLine(finish); } } return sb.ToString(); } public override string ToString() => GetSql(); public object Clone() { var clone = (MockSqlBreakdown)MemberwiseClone(); clone.SetupClauses = new List(SetupClauses); clone.FinishClauses = new System.Collections.ArrayList(FinishClauses); return clone; } } }