Skip to content

Commit f32b6f9

Browse files
chore(test): migrate from xunit v2 to xunit.v3 (#75)
- Migrated test project from xunit v2 to xunit.v3 (2.0.2) - Update async tests for improved cancellation support - Updated usage of fixture (MicrocksAsyncFeatureFixture) for xunit.v3 compatibility Signed-off-by: SebastienDegodez <sebastien.degodez@gmail.com>
1 parent 0975a14 commit f32b6f9

11 files changed

+204
-255
lines changed

tests/Microcks.Testcontainers.Tests/Async/Amqp/MicrocksAsyncAmqpFeatureTest.cs

Lines changed: 12 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
// you may not use this file except in compliance with the License.
66
// You may obtain a copy of the License at
77
//
8-
// http://www.apache.org/licenses/LICENSE-2.0
8+
// http://www.apache.org/licenses/LICENSE-2.0
99
//
1010
// Unless required by applicable law or agreed to in writing, software
1111
// distributed under the License is distributed on an "AS IS" BASIS,
@@ -32,7 +32,7 @@ public class MicrocksAsyncAmqpFeatureTest : IAsyncLifetime
3232
private MicrocksContainerEnsemble _ensemble;
3333
private INetwork _network;
3434

35-
public async Task InitializeAsync()
35+
public async ValueTask InitializeAsync()
3636
{
3737
_network = new NetworkBuilder().Build();
3838
_rabbitMqContainer = new RabbitMqBuilder()
@@ -53,14 +53,15 @@ await _rabbitMqContainer.StartAsync()
5353
await _ensemble.StartAsync();
5454
}
5555

56-
public async Task DisposeAsync()
56+
public async ValueTask DisposeAsync()
5757
{
5858
if (_ensemble != null)
5959
await _ensemble.DisposeAsync();
6060
if (_rabbitMqContainer != null)
6161
await _rabbitMqContainer.DisposeAsync();
6262
if (_network != null)
6363
await _network.DisposeAsync();
64+
GC.SuppressFinalize(this);
6465
}
6566

6667
[Fact]
@@ -79,28 +80,28 @@ public async Task ShouldReceiveAmqpMockMessageWhenMicrocksAsyncMinonEmits()
7980
};
8081

8182
string receivedMessage = null;
82-
using var connection = await factory.CreateConnectionAsync();
83-
using var channel = await connection.CreateChannelAsync();
83+
await using var connection = await factory.CreateConnectionAsync(cancellationToken: TestContext.Current.CancellationToken);
84+
await using var channel = await connection.CreateChannelAsync(cancellationToken: TestContext.Current.CancellationToken);
8485

85-
await channel.ExchangeDeclareAsync(amqpDestination, "topic", false);
86-
var queueDeclareResult = await channel.QueueDeclareAsync();
86+
await channel.ExchangeDeclareAsync(amqpDestination, "topic", false, cancellationToken: TestContext.Current.CancellationToken);
87+
var queueDeclareResult = await channel.QueueDeclareAsync(cancellationToken: TestContext.Current.CancellationToken);
8788
var queueName = queueDeclareResult.QueueName;
88-
await channel.QueueBindAsync(queueName, amqpDestination, "#");
89+
await channel.QueueBindAsync(queueName, amqpDestination, "#", cancellationToken: TestContext.Current.CancellationToken);
8990

9091
var consumer = new AsyncEventingBasicConsumer(channel);
9192
var messageReceived = new ManualResetEventSlim(false);
9293

9394
consumer.ReceivedAsync += async (model, ea) =>
9495
{
9596
receivedMessage = System.Text.Encoding.UTF8.GetString(ea.Body.ToArray());
96-
await channel.BasicAckAsync(ea.DeliveryTag, false);
97+
await channel.BasicAckAsync(ea.DeliveryTag, false, cancellationToken: TestContext.Current.CancellationToken);
9798
messageReceived.Set();
9899
};
99100

100-
await channel.BasicConsumeAsync(queue: queueName, autoAck: false, consumer: consumer);
101+
await channel.BasicConsumeAsync(queue: queueName, autoAck: false, consumer: consumer, cancellationToken: TestContext.Current.CancellationToken);
101102

102103
// Attendre le message (timeout 5s)
103-
messageReceived.Wait(TimeSpan.FromSeconds(5));
104+
messageReceived.Wait(TimeSpan.FromSeconds(5), TestContext.Current.CancellationToken);
104105

105106
Assert.NotNull(receivedMessage);
106107
Assert.True(receivedMessage.Length > 1);

tests/Microcks.Testcontainers.Tests/Async/Kafka/MicrocksAsyncKafkaFunctionalityTest.cs

Lines changed: 8 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,6 @@
1616
//
1717

1818
using System;
19-
using System.Collections.Generic;
2019
using System.Diagnostics;
2120
using System.Linq;
2221
using Confluent.Kafka;
@@ -40,13 +39,13 @@ public sealed class MicrocksAsyncKafkaFunctionalityTest : IAsyncLifetime
4039

4140
private KafkaContainer _kafkaContainer;
4241

43-
public async Task DisposeAsync()
42+
public async ValueTask DisposeAsync()
4443
{
4544
await this._microcksContainerEnsemble.DisposeAsync();
4645
await this._kafkaContainer.DisposeAsync();
4746
}
4847

49-
public async Task InitializeAsync()
48+
public async ValueTask InitializeAsync()
5049
{
5150
var network = new NetworkBuilder().Build();
5251

@@ -150,7 +149,7 @@ public async Task ShouldReturnsCorrectStatusContractWhenGoodMessageIsEmitted()
150149
.MicrocksContainer
151150
.TestEndpointAsync(testRequest);
152151

153-
await Task.Delay(750);
152+
await Task.Delay(750, TestContext.Current.CancellationToken);
154153

155154
// Act
156155
for (var i = 0; i < 5; i++)
@@ -160,8 +159,8 @@ public async Task ShouldReturnsCorrectStatusContractWhenGoodMessageIsEmitted()
160159
Key = Guid.NewGuid().ToString(),
161160
Value = message
162161
});
163-
producer.Flush();
164-
await Task.Delay(500);
162+
producer.Flush(TestContext.Current.CancellationToken);
163+
await Task.Delay(500, TestContext.Current.CancellationToken);
165164
}
166165

167166
// Wait for a test result
@@ -219,7 +218,7 @@ public async Task ShouldReturnsCorrectStatusContractWhenBadMessageIsEmitted()
219218
var taskTestResult = this._microcksContainerEnsemble
220219
.MicrocksContainer
221220
.TestEndpointAsync(testRequest);
222-
await Task.Delay(750);
221+
await Task.Delay(750, TestContext.Current.CancellationToken);
223222

224223
// Act
225224
for (var i = 0; i < 5; i++)
@@ -229,8 +228,8 @@ public async Task ShouldReturnsCorrectStatusContractWhenBadMessageIsEmitted()
229228
Key = Guid.NewGuid().ToString(),
230229
Value = message
231230
});
232-
producer.Flush();
233-
await Task.Delay(500);
231+
producer.Flush(TestContext.Current.CancellationToken);
232+
await Task.Delay(500, TestContext.Current.CancellationToken);
234233
}
235234

236235
// Wait for a test result
Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,89 @@
1+
//
2+
// Copyright The Microcks Authors.
3+
//
4+
// Licensed under the Apache License, Version 2.0 (the "License")
5+
// you may not use this file except in compliance with the License.
6+
// You may obtain a copy of the License at
7+
//
8+
// http://www.apache.org/licenses/LICENSE-2.0
9+
//
10+
// Unless required by applicable law or agreed to in writing, software
11+
// distributed under the License is distributed on an "AS IS" BASIS,
12+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
// See the License for the specific language governing permissions and
14+
// limitations under the License.
15+
//
16+
//
17+
18+
using System;
19+
using DotNet.Testcontainers;
20+
using DotNet.Testcontainers.Builders;
21+
using DotNet.Testcontainers.Containers;
22+
23+
namespace Microcks.Testcontainers.Tests.Async;
24+
25+
[CollectionDefinition(nameof(MicrocksAsyncFeatureCollection))]
26+
public class MicrocksAsyncFeatureCollection : ICollectionFixture<MicrocksAsyncFeatureFixture> { }
27+
28+
/// <summary>
29+
/// Fixture for Microcks Async Feature tests.
30+
/// </summary>
31+
public class MicrocksAsyncFeatureFixture : IAsyncLifetime
32+
{
33+
/// <summary>
34+
/// Image name for the Microcks container.
35+
/// </summary>
36+
private const string MicrocksImage = "quay.io/microcks/microcks-uber:1.10.1-native";
37+
38+
private const string BadPastryAsyncImage = "quay.io/microcks/contract-testing-demo-async:01";
39+
private const string GoodPastryAsyncImage = "quay.io/microcks/contract-testing-demo-async:02";
40+
41+
public MicrocksContainerEnsemble MicrocksContainerEnsemble { get; private set; }
42+
private IContainer WsGoodImplContainer { get; set; }
43+
private IContainer WsBadImplContainer { get; set; }
44+
45+
46+
public async ValueTask DisposeAsync()
47+
{
48+
await this.MicrocksContainerEnsemble.DisposeAsync();
49+
await this.WsBadImplContainer.DisposeAsync();
50+
await this.WsGoodImplContainer.DisposeAsync();
51+
GC.SuppressFinalize(this);
52+
}
53+
54+
public async ValueTask InitializeAsync()
55+
{
56+
ConsoleLogger.Instance.DebugLogLevelEnabled = true;
57+
58+
this.MicrocksContainerEnsemble = new MicrocksContainerEnsemble(MicrocksImage)
59+
.WithMainArtifacts("pastry-orders-asyncapi.yml")
60+
.WithAsyncFeature();
61+
62+
this.WsBadImplContainer = new ContainerBuilder()
63+
.WithImage(BadPastryAsyncImage)
64+
.WithNetwork(this.MicrocksContainerEnsemble.Network)
65+
.WithNetworkAliases("bad-impl")
66+
.WithExposedPort(4001)
67+
.WithWaitStrategy(
68+
Wait.ForUnixContainer()
69+
.UntilMessageIsLogged(".*Starting WebSocket server on ws://localhost:4001/websocket.*")
70+
)
71+
.Build();
72+
73+
this.WsGoodImplContainer = new ContainerBuilder()
74+
.WithImage(GoodPastryAsyncImage)
75+
.WithNetwork(this.MicrocksContainerEnsemble.Network)
76+
.WithNetworkAliases("good-impl")
77+
.WithExposedPort(4002)
78+
.WithWaitStrategy(
79+
Wait.ForUnixContainer()
80+
.UntilMessageIsLogged(".*Starting WebSocket server on ws://localhost:4002/websocket.*")
81+
)
82+
.Build();
83+
84+
await this.MicrocksContainerEnsemble.StartAsync();
85+
await this.WsBadImplContainer.StartAsync();
86+
await this.WsGoodImplContainer.StartAsync();
87+
}
88+
89+
}

tests/Microcks.Testcontainers.Tests/Async/MicrocksAsyncFeatureTest.cs

Lines changed: 42 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -21,76 +21,26 @@
2121
using System.Net.WebSockets;
2222
using System.Text;
2323
using System.Threading;
24-
using DotNet.Testcontainers;
25-
using DotNet.Testcontainers.Builders;
26-
using DotNet.Testcontainers.Containers;
2724
using Microcks.Testcontainers.Model;
2825
using Microsoft.Extensions.Logging;
2926

3027
namespace Microcks.Testcontainers.Tests.Async;
3128

32-
[Collection(nameof(WsCollection))]
33-
public sealed class MicrocksAsyncFeatureTest : IAsyncLifetime
29+
[Collection(nameof(MicrocksAsyncFeatureCollection))]
30+
public sealed class MicrocksAsyncFeatureTest
3431
{
35-
/// <summary>
36-
/// Image name for the Microcks container.
37-
/// </summary>
38-
private const string MicrocksImage = "quay.io/microcks/microcks-uber:1.10.1-native";
39-
40-
private const string BadPastryAsyncImage = "quay.io/microcks/contract-testing-demo-async:01";
41-
private const string GoodPastryAsyncImage = "quay.io/microcks/contract-testing-demo-async:02";
42-
43-
private MicrocksContainerEnsemble _microcksContainerEnsemble;
44-
private IContainer _wsGoodImplContainer;
45-
private IContainer _wsBadImplContainer;
32+
private readonly MicrocksAsyncFeatureFixture fixture;
4633

47-
public async Task DisposeAsync()
34+
public MicrocksAsyncFeatureTest(MicrocksAsyncFeatureFixture fixture)
4835
{
49-
await this._microcksContainerEnsemble.DisposeAsync();
50-
await this._wsBadImplContainer.DisposeAsync();
51-
await this._wsGoodImplContainer.DisposeAsync();
52-
}
53-
54-
public async Task InitializeAsync()
55-
{
56-
ConsoleLogger.Instance.DebugLogLevelEnabled = true;
57-
58-
this._microcksContainerEnsemble = new MicrocksContainerEnsemble(MicrocksImage)
59-
.WithMainArtifacts("pastry-orders-asyncapi.yml")
60-
.WithAsyncFeature();
61-
62-
this._wsBadImplContainer = new ContainerBuilder()
63-
.WithImage(BadPastryAsyncImage)
64-
.WithNetwork(this._microcksContainerEnsemble.Network)
65-
.WithNetworkAliases("bad-impl")
66-
.WithExposedPort(4001)
67-
.WithWaitStrategy(
68-
Wait.ForUnixContainer()
69-
.UntilMessageIsLogged(".*Starting WebSocket server on ws://localhost:4001/websocket.*")
70-
)
71-
.Build();
72-
73-
this._wsGoodImplContainer = new ContainerBuilder()
74-
.WithImage(GoodPastryAsyncImage)
75-
.WithNetwork(this._microcksContainerEnsemble.Network)
76-
.WithNetworkAliases("good-impl")
77-
.WithExposedPort(4002)
78-
.WithWaitStrategy(
79-
Wait.ForUnixContainer()
80-
.UntilMessageIsLogged(".*Starting WebSocket server on ws://localhost:4002/websocket.*")
81-
)
82-
.Build();
83-
84-
await this._microcksContainerEnsemble.StartAsync();
85-
await this._wsBadImplContainer.StartAsync();
86-
await this._wsGoodImplContainer.StartAsync();
36+
this.fixture = fixture;
8737
}
8838

8939
[Fact]
9040
public void ShouldDetermineCorrectImageMessage()
9141
{
9242
Assert.Equal("quay.io/microcks/microcks-uber-async-minion:1.10.1",
93-
this._microcksContainerEnsemble.AsyncMinionContainer.Image.FullName);
43+
this.fixture.MicrocksContainerEnsemble.AsyncMinionContainer.Image.FullName);
9444
}
9545

9646
/// <summary>
@@ -101,7 +51,8 @@ public void ShouldDetermineCorrectImageMessage()
10151
public async Task ShouldReceivedWebSocketMessageWhenMessageIsEmitted()
10252
{
10353
// Get the WebSocket endpoint for the "Pastry orders API" with version "0.1.0" and subscription "SUBSCRIBE pastry/orders".
104-
var webSocketEndpoint = _microcksContainerEnsemble
54+
var webSocketEndpoint = fixture
55+
.MicrocksContainerEnsemble
10556
.AsyncMinionContainer
10657
.GetWebSocketMockEndpoint("Pastry orders API", "0.1.0", "SUBSCRIBE pastry/orders");
10758
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\"}]}";
@@ -139,15 +90,15 @@ public async Task ShouldReturnsCorrectStatusContractWhenBadMessageIsEmitted()
13990
TestEndpoint = "ws://bad-impl:4001/websocket",
14091
};
14192

142-
var taskTestResult = _microcksContainerEnsemble.MicrocksContainer
93+
var taskTestResult = fixture.MicrocksContainerEnsemble.MicrocksContainer
14394
.TestEndpointAsync(testRequest);
14495

14596
stopwatch.Start();
14697
var testResult = await taskTestResult;
14798
stopwatch.Stop();
14899

149100
// Add logging to trace the test result
150-
var logger = _microcksContainerEnsemble
101+
var logger = fixture.MicrocksContainerEnsemble
151102
.MicrocksContainer
152103
.Logger;
153104

@@ -184,7 +135,7 @@ public async Task ShouldReturnsCorrectStatusContractWhenGoodMessageIsEmitted()
184135
TestEndpoint = "ws://good-impl:4002/websocket",
185136
};
186137

187-
var taskTestResult = _microcksContainerEnsemble.MicrocksContainer
138+
var taskTestResult = fixture.MicrocksContainerEnsemble.MicrocksContainer
188139
.TestEndpointAsync(testRequest);
189140

190141
var testResult = await taskTestResult;
@@ -197,4 +148,35 @@ public async Task ShouldReturnsCorrectStatusContractWhenGoodMessageIsEmitted()
197148
Assert.NotEmpty(testResult.TestCaseResults.First().TestStepResults);
198149
Assert.True(string.IsNullOrEmpty(testResult.TestCaseResults.First().TestStepResults.First().Message));
199150
}
151+
152+
/// <summary>
153+
/// Test that verifies that the WaitForConditionAsync method throws a TaskCanceledException
154+
/// when the specified timeout is reached.
155+
/// </summary>
156+
[Fact]
157+
public async Task WaitForConditionAsyncShouldThrowTaskCanceledExceptionWhenTimeoutIsReached()
158+
{
159+
// New Test request
160+
var testRequest = new TestRequest
161+
{
162+
ServiceId = "Pastry orders API:0.1.0",
163+
RunnerType = TestRunnerType.ASYNC_API_SCHEMA,
164+
Timeout = TimeSpan.FromMilliseconds(200),
165+
TestEndpoint = "ws://good-impl:4002/websocket",
166+
};
167+
168+
var taskTestResult = fixture.MicrocksContainerEnsemble.MicrocksContainer
169+
.TestEndpointAsync(testRequest);
170+
171+
var stopwatch = new Stopwatch();
172+
stopwatch.Start();
173+
var testResult = await taskTestResult;
174+
stopwatch.Stop();
175+
176+
// Assert
177+
Assert.True(stopwatch.ElapsedMilliseconds > 200);
178+
Assert.True(testResult.InProgress);
179+
Assert.False(testResult.Success);
180+
Assert.Equal(testRequest.TestEndpoint, testResult.TestedEndpoint);
181+
}
200182
}

0 commit comments

Comments
 (0)