1515//
1616//
1717
18+ using System ;
19+ using System . Linq ;
20+ using System . Net . WebSockets ;
21+ using System . Text ;
22+ using System . Threading ;
23+ using DotNet . Testcontainers . Builders ;
24+ using DotNet . Testcontainers . Containers ;
1825using FluentAssertions ;
26+ using Microcks . Testcontainers . Model ;
1927
2028namespace Microcks . Testcontainers . Tests . Async ;
2129
@@ -26,19 +34,51 @@ public sealed class MicrocksAsyncFeatureTest : IAsyncLifetime
2634 /// </summary>
2735 private const string MicrocksImage = "quay.io/microcks/microcks-uber:1.10.1-native" ;
2836
37+ private const string BadPastryAsyncImage = "quay.io/microcks/contract-testing-demo-async:01" ;
38+ private const string GoodPastryAsyncImage = "quay.io/microcks/contract-testing-demo-async:02" ;
39+
2940 private MicrocksContainerEnsemble _microcksContainerEnsemble ;
41+ private IContainer _wsGoodImplContainer ;
42+ private IContainer _wsBadImplContainer ;
3043
3144 public async Task DisposeAsync ( )
3245 {
3346 await this . _microcksContainerEnsemble . DisposeAsync ( ) ;
47+ await this . _wsBadImplContainer . DisposeAsync ( ) ;
48+ await this . _wsGoodImplContainer . DisposeAsync ( ) ;
3449 }
3550
3651 public async Task InitializeAsync ( )
3752 {
3853 this . _microcksContainerEnsemble = new MicrocksContainerEnsemble ( MicrocksImage )
54+ . WithMainArtifacts ( "pastry-orders-asyncapi.yml" )
3955 . WithAsyncFeature ( ) ;
4056
57+ this . _wsBadImplContainer = new ContainerBuilder ( )
58+ . WithImage ( BadPastryAsyncImage )
59+ . WithNetwork ( this . _microcksContainerEnsemble . Network )
60+ . WithNetworkAliases ( "bad-impl" )
61+ . WithExposedPort ( 4001 )
62+ . WithWaitStrategy (
63+ Wait . ForUnixContainer ( )
64+ . UntilMessageIsLogged ( ".*Starting WebSocket server on ws://localhost:4001/websocket.*" )
65+ )
66+ . Build ( ) ;
67+
68+ this . _wsGoodImplContainer = new ContainerBuilder ( )
69+ . WithImage ( GoodPastryAsyncImage )
70+ . WithNetwork ( this . _microcksContainerEnsemble . Network )
71+ . WithNetworkAliases ( "good-impl" )
72+ . WithExposedPort ( 4002 )
73+ . WithWaitStrategy (
74+ Wait . ForUnixContainer ( )
75+ . UntilMessageIsLogged ( ".*Starting WebSocket server on ws://localhost:4002/websocket.*" )
76+ )
77+ . Build ( ) ;
78+
4179 await this . _microcksContainerEnsemble . StartAsync ( ) ;
80+ await this . _wsBadImplContainer . StartAsync ( ) ;
81+ await this . _wsGoodImplContainer . StartAsync ( ) ;
4282 }
4383
4484 [ Fact ]
@@ -49,4 +89,92 @@ public void ShouldDetermineCorrectImageMessage()
4989 . Be ( "quay.io/microcks/microcks-uber-async-minion:1.10.1" ) ;
5090 }
5191
92+ /// <summary>
93+ /// Test method to verify that a WebSocket message is received when a message is emitted.
94+ /// </summary>
95+ /// <returns>A task that represents the asynchronous operation.</returns>
96+ [ Fact ]
97+ public async Task ShouldReceivedWebSocketMessageWhenMessageIsEmitted ( )
98+ {
99+ // Get the WebSocket endpoint for the "Pastry orders API" with version "0.1.0" and subscription "SUBSCRIBE pastry/orders".
100+ var webSocketEndpoint = _microcksContainerEnsemble
101+ . AsyncMinionContainer
102+ . GetWebSocketMockEndpoint ( "Pastry orders API" , "0.1.0" , "SUBSCRIBE pastry/orders" ) ;
103+ 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\" }]}" ;
104+
105+ using var webSocketClient = new ClientWebSocket ( ) ;
106+ await webSocketClient . ConnectAsync ( webSocketEndpoint , CancellationToken . None ) ;
107+
108+ var buffer = new byte [ 1024 ] ;
109+
110+ var cts = new CancellationTokenSource ( TimeSpan . FromSeconds ( 7 ) ) ;
111+ var result = await webSocketClient . ReceiveAsync ( new ArraySegment < byte > ( buffer ) , cts . Token ) ;
112+ var message = Encoding . UTF8 . GetString ( buffer , 0 , result . Count ) ;
113+
114+ await webSocketClient . CloseAsync (
115+ WebSocketCloseStatus . NormalClosure ,
116+ "Test done" ,
117+ CancellationToken . None ) ;
118+
119+ message . Should ( ) . Be ( expectedMessage ) ;
120+ }
121+
122+ /// <summary>
123+ /// Test that verifies the correct status contract when a bad message is emitted.
124+ /// </summary>
125+ [ Fact ]
126+ public async Task ShouldReturnsCorrectStatusContractWhenBadMessageIsEmitted ( )
127+ {
128+ // New Test request
129+ var testRequest = new TestRequest
130+ {
131+ ServiceId = "Pastry orders API:0.1.0" ,
132+ RunnerType = TestRunnerType . ASYNC_API_SCHEMA ,
133+ Timeout = TimeSpan . FromMilliseconds ( 70000 ) ,
134+ TestEndpoint = "ws://bad-impl:4001/websocket" ,
135+ } ;
136+
137+ var taskTestResult = _microcksContainerEnsemble . MicrocksContainer
138+ . TestEndpointAsync ( testRequest ) ;
139+
140+ var testResult = await taskTestResult ;
141+
142+ // Assert
143+ testResult . InProgress . Should ( ) . Be ( false ) ;
144+ testResult . Success . Should ( ) . Be ( false ) ;
145+ testResult . TestedEndpoint . Should ( ) . Be ( testRequest . TestEndpoint ) ;
146+
147+ testResult . TestCaseResults . First ( ) . TestStepResults . Should ( ) . NotBeEmpty ( ) ;
148+ var testStepResult = testResult . TestCaseResults . First ( ) . TestStepResults . First ( ) ;
149+ testStepResult . Message . Should ( ) . Contain ( "object has missing required properties ([\" status\" ]" ) ;
150+ }
151+
152+ /// <summary>
153+ /// Test that verifies the correct status contract when a good message is emitted.
154+ /// </summary>
155+ [ Fact ]
156+ public async Task ShouldReturnsCorrectStatusContractWhenGoodMessageIsEmitted ( )
157+ {
158+ // New Test request
159+ var testRequest = new TestRequest
160+ {
161+ ServiceId = "Pastry orders API:0.1.0" ,
162+ RunnerType = TestRunnerType . ASYNC_API_SCHEMA ,
163+ Timeout = TimeSpan . FromMilliseconds ( 7000 ) ,
164+ TestEndpoint = "ws://good-impl:4002/websocket" ,
165+ } ;
166+
167+ var taskTestResult = _microcksContainerEnsemble . MicrocksContainer
168+ . TestEndpointAsync ( testRequest ) ;
169+
170+ var testResult = await taskTestResult ;
171+
172+ // Assert
173+ testResult . InProgress . Should ( ) . Be ( false ) ;
174+ testResult . Success . Should ( ) . Be ( true ) ;
175+ testResult . TestedEndpoint . Should ( ) . Be ( testRequest . TestEndpoint ) ;
176+
177+ testResult . TestCaseResults . First ( ) . TestStepResults . Should ( ) . NotBeEmpty ( ) ;
178+ testResult . TestCaseResults . First ( ) . TestStepResults . First ( ) . Message . Should ( ) . BeNullOrEmpty ( ) ;
179+ }
52180}
0 commit comments