@@ -6,6 +6,7 @@ namespace Serilog.Sinks.MongoDB.Tests;
66/// instead of string matching, ensuring compatibility across MongoDB versions.
77/// </summary>
88[ TestFixture ]
9+ [ NonParallelizable ]
910public class MongoDbHelperErrorHandlingTests
1011{
1112 private static string MongoConnectionString => MongoTestFixture . ConnectionString ;
@@ -24,7 +25,6 @@ private static (MongoClient, IMongoDatabase) GetDatabase()
2425 public void Cleanup ( )
2526 {
2627 var mongoClient = new MongoClient ( MongoConnectionString ) ;
27- mongoClient . DropDatabase ( MongoDatabaseName ) ;
2828 }
2929
3030 #region VerifyCollectionExists Tests
@@ -42,8 +42,6 @@ public void VerifyCollectionExists_WhenCollectionDoesNotExist_ShouldCreateCollec
4242 // Assert
4343 var collectionExists = mongoDatabase . CollectionExists ( collectionName ) ;
4444 collectionExists . Should ( ) . BeTrue ( "Collection should be created when it doesn't exist" ) ;
45-
46- mongoClient . DropDatabase ( MongoDatabaseName ) ;
4745 }
4846
4947 [ Test ]
@@ -59,8 +57,6 @@ public void VerifyCollectionExists_WhenCollectionAlreadyExists_ShouldNotThrowExc
5957 // Act & Assert - Should not throw when collection already exists
6058 var act = ( ) => mongoDatabase . VerifyCollectionExists ( collectionName ) ;
6159 act . Should ( ) . NotThrow ( "VerifyCollectionExists should handle existing collections gracefully" ) ;
62-
63- mongoClient . DropDatabase ( MongoDatabaseName ) ;
6460 }
6561
6662 [ Test ]
@@ -70,18 +66,19 @@ public void VerifyCollectionExists_WithRaceCondition_ShouldHandleNamespaceExists
7066 var ( mongoClient , mongoDatabase ) = GetDatabase ( ) ;
7167 var collectionName = $ "{ MongoCollectionName } _race";
7268
73- // Pre-create the collection but the method doesn't know about it
74- // This simulates a race condition where CollectionExists returns false
75- // but the collection gets created before CreateCollection is called
76- mongoDatabase . CreateCollection ( collectionName ) ;
69+ // Act & Assert - Simulate race condition by calling verify concurrently
70+ // This forces actual NamespaceExists exceptions when multiple threads
71+ // try to create the same collection simultaneously
72+ var act = ( ) => Parallel . Invoke (
73+ ( ) => mongoDatabase . VerifyCollectionExists ( collectionName ) ,
74+ ( ) => mongoDatabase . VerifyCollectionExists ( collectionName ) ,
75+ ( ) => mongoDatabase . VerifyCollectionExists ( collectionName )
76+ ) ;
7777
78- // Act & Assert - Even though it exists, should handle gracefully
79- // The internal check will see it exists and return early,
80- // but if it didn't, the catch block should handle NamespaceExists
81- var act = ( ) => mongoDatabase . VerifyCollectionExists ( collectionName ) ;
82- act . Should ( ) . NotThrow ( "Should handle NamespaceExists error code gracefully" ) ;
78+ act . Should ( ) . NotThrow ( "Should handle NamespaceExists error code gracefully during concurrent creation" ) ;
8379
84- mongoClient . DropDatabase ( MongoDatabaseName ) ;
80+ // Verify the collection was created successfully
81+ mongoDatabase . CollectionExists ( collectionName ) . Should ( ) . BeTrue ( ) ;
8582 }
8683
8784 [ Test ]
@@ -103,8 +100,6 @@ public void VerifyCollectionExists_WithCollectionCreationOptions_ShouldCreateWit
103100 // Assert
104101 var collectionExists = mongoDatabase . CollectionExists ( collectionName ) ;
105102 collectionExists . Should ( ) . BeTrue ( "Collection should be created with options" ) ;
106-
107- mongoClient . DropDatabase ( MongoDatabaseName ) ;
108103 }
109104
110105 #endregion
@@ -132,9 +127,10 @@ public void VerifyExpireTTLSetup_WhenNoIndexExists_ShouldCreateTTLIndex()
132127 idx . Contains ( "name" ) && idx [ "name" ] . AsString == "serilog_sink_expired_ttl" ) ;
133128
134129 ttlIndex . Should ( ) . NotBeNull ( "TTL index should be created" ) ;
135- ttlIndex ! [ "expireAfterSeconds" ] . Should ( ) . Be ( ( int ) expireTtl . TotalSeconds ) ;
130+ // Convert to long to handle MongoDB's potential Int64 or Double serialization across versions
131+ Convert . ToInt64 ( ttlIndex ! [ "expireAfterSeconds" ] . ToDouble ( ) )
132+ . Should ( ) . Be ( ( long ) expireTtl . TotalSeconds ) ;
136133
137- mongoClient . DropDatabase ( MongoDatabaseName ) ;
138134 }
139135
140136 [ Test ]
@@ -161,7 +157,6 @@ public void VerifyExpireTTLSetup_WhenIndexExistsWithSameOptions_ShouldNotThrow()
161157 var act = ( ) => mongoDatabase . VerifyExpireTTLSetup ( collectionName , expireTtl ) ;
162158 act . Should ( ) . NotThrow ( "Should handle existing TTL index with same options" ) ;
163159
164- mongoClient . DropDatabase ( MongoDatabaseName ) ;
165160 }
166161
167162 [ Test ]
@@ -195,10 +190,11 @@ public void VerifyExpireTTLSetup_WhenIndexExistsWithDifferentOptions_ShouldRecre
195190 idx . Contains ( "name" ) && idx [ "name" ] . AsString == "serilog_sink_expired_ttl" ) ;
196191
197192 ttlIndex . Should ( ) . NotBeNull ( "TTL index should still exist" ) ;
198- ttlIndex ! [ "expireAfterSeconds" ] . Should ( ) . Be ( ( int ) newExpireTtl . TotalSeconds ,
199- "Index should be recreated with new expiration time" ) ;
193+ // Convert to long to handle MongoDB's potential Int64 or Double serialization across versions
194+ Convert . ToInt64 ( ttlIndex ! [ "expireAfterSeconds" ] . ToDouble ( ) )
195+ . Should ( ) . Be ( ( long ) newExpireTtl . TotalSeconds ,
196+ "Index should be recreated with new expiration time" ) ;
200197
201- mongoClient . DropDatabase ( MongoDatabaseName ) ;
202198 }
203199
204200 [ Test ]
@@ -231,7 +227,6 @@ public void VerifyExpireTTLSetup_WhenNullExpireTTL_ShouldRemoveIndex()
231227
232228 ttlIndex . Should ( ) . BeNull ( "TTL index should be removed when expireTTL is null" ) ;
233229
234- mongoClient . DropDatabase ( MongoDatabaseName ) ;
235230 }
236231
237232 [ Test ]
@@ -247,7 +242,6 @@ public void VerifyExpireTTLSetup_WhenNullExpireTTLAndNoIndex_ShouldNotThrow()
247242 var act = ( ) => mongoDatabase . VerifyExpireTTLSetup ( collectionName , null ) ;
248243 act . Should ( ) . NotThrow ( "Should handle removal of non-existent index gracefully" ) ;
249244
250- mongoClient . DropDatabase ( MongoDatabaseName ) ;
251245 }
252246
253247 [ Test ]
@@ -272,9 +266,10 @@ public void VerifyExpireTTLSetup_MultipleTimes_ShouldBeIdempotent()
272266 idx . Contains ( "name" ) && idx [ "name" ] . AsString == "serilog_sink_expired_ttl" ) . ToList ( ) ;
273267
274268 ttlIndexes . Should ( ) . HaveCount ( 1 , "Should only have one TTL index even after multiple calls" ) ;
275- ttlIndexes [ 0 ] [ "expireAfterSeconds" ] . Should ( ) . Be ( ( int ) expireTtl . TotalSeconds ) ;
269+ // Convert to long to handle MongoDB's potential Int64 or Double serialization across versions
270+ Convert . ToInt64 ( ttlIndexes [ 0 ] [ "expireAfterSeconds" ] . ToDouble ( ) )
271+ . Should ( ) . Be ( ( long ) expireTtl . TotalSeconds ) ;
276272
277- mongoClient . DropDatabase ( MongoDatabaseName ) ;
278273 }
279274
280275 #endregion
@@ -323,7 +318,6 @@ public void MongoCommandException_WhenCollectionExists_ShouldHaveNamespaceExists
323318 "MongoDB should return CodeName 'NamespaceExists' for duplicate collection" ) ;
324319 caughtException . Code . Should ( ) . Be ( 48 , "Error code should be 48 for NamespaceExists" ) ;
325320
326- mongoClient . DropDatabase ( MongoDatabaseName ) ;
327321 }
328322
329323 /// <summary>
@@ -371,7 +365,6 @@ public void MongoCommandException_WhenIndexExistsWithDifferentOptions_ShouldHave
371365 "MongoDB should return CodeName 'IndexOptionsConflict' for index with different options" ) ;
372366 caughtException . Code . Should ( ) . Be ( 85 , "Error code should be 85 for IndexOptionsConflict" ) ;
373367
374- mongoClient . DropDatabase ( MongoDatabaseName ) ;
375368 }
376369
377370 #endregion
0 commit comments