1919using Moq ;
2020using Moq . Protected ;
2121using NUnit . Framework ;
22+ using ksqlDb . RestApi . Client . FluentAPI . Builders ;
2223
2324namespace ksqlDb . RestApi . Client . Tests . KSql . RestApi ;
2425
@@ -153,7 +154,7 @@ public async Task CreateContent_KSqlContentWasSet()
153154
154155 //Assert
155156 var content = await GetContent ( stringContent ) ;
156-
157+
157158 content . Should ( ) . Be ( @$ "{{""ksql"":""{ createOrReplaceTableStatement } "",""streamsProperties"":{{}}}}") ;
158159 }
159160
@@ -307,7 +308,7 @@ public async Task GetAllTopicsExtendedAsync()
307308 //Assert
308309 responses . Should ( ) . NotBeNull ( ) ;
309310 var expectedContent = GetExpectedContent ( StatementTemplates . ShowAllTopicsExtended ) ;
310-
311+
311312 VerifySendAsync ( expectedContent ) ;
312313 }
313314
@@ -355,7 +356,7 @@ public async Task TerminatePushQueryAsync()
355356 {
356357 QueryId = queryId
357358 } ;
358-
359+
359360 var expectedContent = await KSqlDbRestApiClient . CreateContent ( closeQuery , Encoding . UTF8 ) . ReadAsStringAsync ( ) ;
360361
361362 VerifySendAsync ( expectedContent , "/close-query" ) ;
@@ -459,7 +460,7 @@ public async Task DropStreamAsync_WithDropEntityProperties()
459460 //Assert
460461 response . Should ( ) . NotBeNull ( ) ;
461462 var expectedContent = GetExpectedContent ( StatementTemplates . DropStream ( streamName , properties . UseIfExistsClause , properties . DeleteTopic ) ) ;
462-
463+
463464 VerifySendAsync ( expectedContent ) ;
464465 }
465466
@@ -479,7 +480,7 @@ public async Task DropStreamAsync_IfExistsAndDeleteTopic()
479480 //Assert
480481 response . Should ( ) . NotBeNull ( ) ;
481482 var expectedContent = GetExpectedContent ( StatementTemplates . DropStream ( streamName , useIfExistsClause , deleteTopic ) ) ;
482-
483+
483484 VerifySendAsync ( expectedContent ) ;
484485 }
485486
@@ -517,7 +518,7 @@ public async Task DropTableAsync_IfExistsAndDeleteTopic()
517518 //Assert
518519 response . Should ( ) . NotBeNull ( ) ;
519520 var expectedContent = GetExpectedContent ( StatementTemplates . DropTable ( tableName , useIfExistsClause , deleteTopic ) ) ;
520-
521+
521522 VerifySendAsync ( expectedContent ) ;
522523 }
523524
@@ -543,7 +544,7 @@ public async Task DropTableAsync_WithDropEntityProperties()
543544 //Assert
544545 response . Should ( ) . NotBeNull ( ) ;
545546 var expectedContent = GetExpectedContent ( StatementTemplates . DropTable ( tableName , properties . UseIfExistsClause , properties . DeleteTopic ) ) ;
546-
547+
547548 VerifySendAsync ( expectedContent ) ;
548549 }
549550
@@ -583,6 +584,54 @@ public void ToInsertStatement()
583584 insertStatement . Sql . Should ( ) . Be ( "INSERT INTO Movies (Title, Id, Release_Year) VALUES (NULL, 1, 0);" ) ;
584585 }
585586
587+ public class POC
588+ {
589+ public int Id { get ; init ; }
590+ public string ? Description { get ; init ; }
591+ public POC2 [ ] ? Entities { get ; init ; }
592+ }
593+
594+ public class POC2
595+ {
596+ public POC3 [ ] ? Poc3 { get ; set ; }
597+ public POC4 [ ] ? Poc4 { get ; set ; }
598+ }
599+
600+ public class POC3
601+ {
602+ public string ? Description { get ; init ; }
603+ }
604+
605+ public class POC4
606+ {
607+ public string ? Description { get ; init ; }
608+ }
609+
610+ public static IEnumerable < ( POC , string ) > NullTestCases ( )
611+ { // empty array constructors are invalid
612+ yield return ( new POC { Id = 1 } , "INSERT INTO POCS (Id, Description, Entities) VALUES (1, NULL, NULL);" ) ;
613+ yield return ( new POC { Id = 1 , Entities = new POC2 [ 0 ] } , "INSERT INTO POCS (Id, Description, Entities) VALUES (1, NULL, ARRAY_REMOVE(ARRAY[0], 0));" ) ;
614+ yield return ( new POC { Id = 1 , Entities = new POC2 [ ] { new POC2 { Poc3 = new POC3 [ 0 ] } } } , "INSERT INTO POCS (Id, Description, Entities) VALUES (1, NULL, ARRAY[STRUCT(Poc3 := ARRAY_REMOVE(ARRAY[0], 0), Poc4 := ARRAY_REMOVE(ARRAY[0], 0))]);" ) ;
615+ yield return ( new POC { Id = 1 , Entities = new POC2 [ ] { new POC2 { Poc3 = new POC3 [ 0 ] , Poc4 = new POC4 [ 0 ] } } } , "INSERT INTO POCS (Id, Description, Entities) VALUES (1, NULL, ARRAY[STRUCT(Poc3 := ARRAY_REMOVE(ARRAY[0], 0), Poc4 := ARRAY_REMOVE(ARRAY[0], 0))]);" ) ;
616+ }
617+
618+ [ TestCaseSource ( nameof ( NullTestCases ) ) ]
619+ public void ToInsertStatement_WithNullHandling ( ( POC , string ) testCase )
620+ {
621+ //Arrange
622+ var ( entity , expected ) = testCase ;
623+ var modelBuilder = new ModelBuilder ( ) ;
624+ modelBuilder . Entity < POC > ( ) . HasKey ( i => i . Id ) ;
625+ modelBuilder . Entity < POC > ( ) . Property ( c => c . Entities ) . AsStruct ( ) ;
626+ var sut = new KSqlDbRestApiClient ( HttpClientFactory , modelBuilder , LoggerFactoryMock . Object ) ;
627+
628+ //Act
629+ var actual = sut . ToInsertStatement ( entity ) ;
630+
631+ //Assert
632+ actual . Sql . Should ( ) . Be ( expected ) ;
633+ }
634+
586635 [ KSqlFunction ]
587636 public static string FormatTimestamp ( long input , string format ) => throw new NotSupportedException ( ) ;
588637
0 commit comments