2424using Microcks . Testcontainers . Model ;
2525using Microsoft . Extensions . Logging ;
2626using Testcontainers . Kafka ;
27+ using DotNet . Testcontainers . Networks ;
2728
2829namespace Microcks . Testcontainers . Tests . Async . Kafka ;
2930
3031[ Collection ( nameof ( KafkaCollection ) ) ]
31- public sealed class MicrocksAsyncKafkaFunctionalityTest : IAsyncLifetime
32+ public sealed class MicrocksAsyncKafkaFunctionalityTest
33+ : IClassFixture < MicrocksAsyncKafkaFunctionalityTest . KafkaFixture >
3234{
3335 /// <summary>
3436 /// Image name for the Microcks container.
3537 /// </summary>
3638 private const string MicrocksImage = "quay.io/microcks/microcks-uber:1.10.0" ;
3739
38- private MicrocksContainerEnsemble _microcksContainerEnsemble ;
40+ private readonly KafkaFixture _fixture ;
3941
40- private KafkaContainer _kafkaContainer ;
41-
42- public async ValueTask DisposeAsync ( )
43- {
44- await this . _microcksContainerEnsemble . DisposeAsync ( ) ;
45- await this . _kafkaContainer . DisposeAsync ( ) ;
46- }
47-
48- public async ValueTask InitializeAsync ( )
42+ public MicrocksAsyncKafkaFunctionalityTest ( KafkaFixture fixture )
4943 {
50- var network = new NetworkBuilder ( ) . Build ( ) ;
51-
52- this . _kafkaContainer = new KafkaBuilder ( )
53- . WithImage ( "confluentinc/cp-kafka:7.8.0" )
54- . WithNetwork ( network )
55- . WithNetworkAliases ( "kafka" )
56- . WithListener ( "kafka:19092" )
57- . Build ( ) ;
58-
59- // Start the Kafka container
60- await this . _kafkaContainer . StartAsync ( ) ;
61-
62- this . _microcksContainerEnsemble = new MicrocksContainerEnsemble ( network , MicrocksImage )
63- . WithMainArtifacts ( "pastry-orders-asyncapi.yml" )
64- . WithKafkaConnection ( new KafkaConnection ( $ "kafka:19092") ) ;
65-
66- await this . _microcksContainerEnsemble . StartAsync ( ) ;
44+ _fixture = fixture ;
6745 }
6846
6947 [ Fact ]
7048 public void ShouldReceivedKafkaMessageWhenMessageIsEmitted ( )
7149 {
7250 const string expectedMessage = "{\" id\" :\" 4dab240d-7847-4e25-8ef3-1530687650c8\" ,\" customerId\" :\" fe1088b3-9f30-4dc1-a93d-7b74f0a072b9\" ,\" status\" :\" VALIDATED\" ,\" productQuantities\" :[{\" quantity\" :2,\" pastryName\" :\" Croissant\" },{\" quantity\" :1,\" pastryName\" :\" Millefeuille\" }]}" ;
73- var kafkaTopic = this . _microcksContainerEnsemble . AsyncMinionContainer
51+ var kafkaTopic = _fixture . MicrocksContainerEnsemble . AsyncMinionContainer
7452 . GetKafkaMockTopic ( "Pastry orders API" , "0.1.0" , "SUBSCRIBE pastry/orders" ) ;
7553
76- var bootstrapServers = this . _kafkaContainer . GetBootstrapAddress ( )
54+ var bootstrapServers = _fixture . KafkaContainer . GetBootstrapAddress ( )
7755 . Replace ( "PLAINTEXT://" , "" , StringComparison . OrdinalIgnoreCase ) ;
7856
7957 // Initialize Kafka consumer to receive message
@@ -127,7 +105,7 @@ public async Task ShouldReturnsCorrectStatusContractWhenGoodMessageIsEmitted()
127105 // Init Kafka producer to send a message
128106 var producerConfig = new ProducerConfig
129107 {
130- BootstrapServers = this . _kafkaContainer . GetBootstrapAddress ( )
108+ BootstrapServers = _fixture . KafkaContainer . GetBootstrapAddress ( )
131109 . Replace ( "PLAINTEXT://" , "" , StringComparison . OrdinalIgnoreCase ) ,
132110 ClientId = $ "test-client-{ DateTime . Now . Ticks } ",
133111 } ;
@@ -137,15 +115,15 @@ public async Task ShouldReturnsCorrectStatusContractWhenGoodMessageIsEmitted()
137115 . SetValueSerializer ( Serializers . Utf8 )
138116 . SetErrorHandler ( ( _ , e ) =>
139117 {
140- this . _kafkaContainer . Logger . LogError ( "Error: {Reason}" , e . Reason ) ;
118+ _fixture . KafkaContainer . Logger . LogError ( "Error: {Reason}" , e . Reason ) ;
141119 } )
142120 . SetLogHandler ( ( _ , logMessage ) =>
143121 {
144- this . _kafkaContainer . Logger . LogInformation ( "{Name} sending {Message}" , logMessage . Name , logMessage . Message ) ;
122+ _fixture . KafkaContainer . Logger . LogInformation ( "{Name} sending {Message}" , logMessage . Name , logMessage . Message ) ;
145123 } )
146124 . Build ( ) ;
147125
148- var taskTestResult = this . _microcksContainerEnsemble
126+ var taskTestResult = _fixture . MicrocksContainerEnsemble
149127 . MicrocksContainer
150128 . TestEndpointAsync ( testRequest , TestContext . Current . CancellationToken ) ;
151129
@@ -197,7 +175,7 @@ public async Task ShouldReturnsCorrectStatusContractWhenBadMessageIsEmitted()
197175 // Init Kafka producer to send a message
198176 var producerConfig = new ProducerConfig
199177 {
200- BootstrapServers = this . _kafkaContainer . GetBootstrapAddress ( )
178+ BootstrapServers = _fixture . KafkaContainer . GetBootstrapAddress ( )
201179 . Replace ( "PLAINTEXT://" , "" , StringComparison . OrdinalIgnoreCase ) ,
202180 ClientId = $ "test-client-{ DateTime . Now . Ticks } ",
203181 } ;
@@ -207,15 +185,15 @@ public async Task ShouldReturnsCorrectStatusContractWhenBadMessageIsEmitted()
207185 . SetValueSerializer ( Serializers . Utf8 )
208186 . SetErrorHandler ( ( _ , e ) =>
209187 {
210- this . _kafkaContainer . Logger . LogError ( "Error: {Reason}" , e . Reason ) ;
188+ _fixture . KafkaContainer . Logger . LogError ( "Error: {Reason}" , e . Reason ) ;
211189 } )
212190 . SetLogHandler ( ( _ , logMessage ) =>
213191 {
214- this . _kafkaContainer . Logger . LogInformation ( "{Name} sending {Message}" , logMessage . Name , logMessage . Message ) ;
192+ _fixture . KafkaContainer . Logger . LogInformation ( "{Name} sending {Message}" , logMessage . Name , logMessage . Message ) ;
215193 } )
216194 . Build ( ) ;
217195
218- var taskTestResult = this . _microcksContainerEnsemble
196+ var taskTestResult = _fixture . MicrocksContainerEnsemble
219197 . MicrocksContainer
220198 . TestEndpointAsync ( testRequest , TestContext . Current . CancellationToken ) ;
221199 await Task . Delay ( 750 , TestContext . Current . CancellationToken ) ;
@@ -249,7 +227,7 @@ public async Task ShouldReturnsCorrectStatusContractWhenBadMessageIsEmitted()
249227 Assert . Contains ( "object has missing required properties ([\" status\" ]" , testStepResults . First ( ) . Message ) ;
250228
251229 // Retrieve event messages for the failing test case.
252- var events = await _microcksContainerEnsemble . MicrocksContainer
230+ var events = await _fixture . MicrocksContainerEnsemble . MicrocksContainer
253231 . GetEventMessagesForTestCaseAsync ( testResult , "SUBSCRIBE pastry/orders" , TestContext . Current . CancellationToken ) ;
254232 // We should have at least 4 events.
255233 Assert . True ( events . Count >= 4 ) ;
@@ -263,4 +241,41 @@ public async Task ShouldReturnsCorrectStatusContractWhenBadMessageIsEmitted()
263241 } ) ;
264242 }
265243
266- }
244+ // Inner fixture to share Kafka and Microcks ensemble between tests
245+ public sealed class KafkaFixture : IAsyncDisposable
246+ {
247+ private const string MicrocksImage = "quay.io/microcks/microcks-uber:1.10.0" ;
248+
249+ public INetwork Network { get ; }
250+ public KafkaContainer KafkaContainer { get ; }
251+ public MicrocksContainerEnsemble MicrocksContainerEnsemble { get ; }
252+
253+ public KafkaFixture ( )
254+ {
255+ Network = new NetworkBuilder ( ) . Build ( ) ;
256+
257+ KafkaContainer = new KafkaBuilder ( )
258+ . WithImage ( "confluentinc/cp-kafka:7.8.0" )
259+ . WithNetwork ( Network )
260+ . WithNetworkAliases ( "kafka" )
261+ . WithListener ( "kafka:19092" )
262+ . Build ( ) ;
263+
264+ KafkaContainer . StartAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
265+
266+ MicrocksContainerEnsemble = new MicrocksContainerEnsemble ( Network , MicrocksImage )
267+ . WithMainArtifacts ( "pastry-orders-asyncapi.yml" )
268+ . WithKafkaConnection ( new KafkaConnection ( $ "kafka:19092") ) ;
269+
270+ MicrocksContainerEnsemble . StartAsync ( ) . GetAwaiter ( ) . GetResult ( ) ;
271+ }
272+
273+ public async ValueTask DisposeAsync ( )
274+ {
275+ await MicrocksContainerEnsemble . DisposeAsync ( ) ;
276+ await KafkaContainer . DisposeAsync ( ) ;
277+ await Network . DisposeAsync ( ) ;
278+ }
279+ }
280+
281+ }
0 commit comments