mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-11 21:10:32 +01:00
Merge branch 'master' into MappingSerializer
This commit is contained in:
@@ -1,3 +1,10 @@
|
||||
# 1.20.0 (24 December 2025)
|
||||
- [#1399](https://github.com/wiremock/WireMock.Net/pull/1399) - Upgrade RamlToOpenApiConverter and YamlDotNet [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1400](https://github.com/wiremock/WireMock.Net/pull/1400) - Add WireMock.Net.NUnit project [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1405](https://github.com/wiremock/WireMock.Net/pull/1405) - Fix Testcontainers AddProtoDefinition [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1398](https://github.com/wiremock/WireMock.Net/issues/1398) - Upgrade YamlDotNet dependency [feature]
|
||||
- [#1404](https://github.com/wiremock/WireMock.Net/issues/1404) - An exception occurs when adding multiple proto definitions in the TestContainer. [bug]
|
||||
|
||||
# 1.19.0 (12 December 2025)
|
||||
- [#1391](https://github.com/wiremock/WireMock.Net/pull/1391) - Update WireMockContainerBuilder (WithImage and WithCustomImage) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1392](https://github.com/wiremock/WireMock.Net/pull/1392) - WireMockContainerBuilder: allow all docker images named wiremock [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.19.0</VersionPrefix>
|
||||
<VersionPrefix>1.20.0</VersionPrefix>
|
||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
rem https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
SET version=1.19.0
|
||||
SET version=1.20.0
|
||||
|
||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels wontfix test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
|
||||
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# 1.19.0 (12 December 2025)
|
||||
- #1391 Update WireMockContainerBuilder (WithImage and WithCustomImage) [feature]
|
||||
- #1392 WireMockContainerBuilder: allow all docker images named wiremock [feature]
|
||||
- #1390 Unable to build WireMockContainerBuilder with custom image [feature]
|
||||
# 1.20.0 (24 December 2025)
|
||||
- #1399 Upgrade RamlToOpenApiConverter and YamlDotNet [feature]
|
||||
- #1400 Add WireMock.Net.NUnit project [feature]
|
||||
- #1405 Fix Testcontainers AddProtoDefinition [bug]
|
||||
- #1398 Upgrade YamlDotNet dependency [feature]
|
||||
- #1404 An exception occurs when adding multiple proto definitions in the TestContainer. [bug]
|
||||
|
||||
The full release notes can be found here: https://github.com/wiremock/WireMock.Net/blob/master/CHANGELOG.md
|
||||
@@ -96,14 +96,14 @@ public class ProtoBufMatcher : IProtoBufMatcher
|
||||
}
|
||||
|
||||
var protoDefinitions = ProtoDefinition().Texts;
|
||||
|
||||
|
||||
var resolver = new WireMockProtoFileResolver(protoDefinitions);
|
||||
var request = new ConvertToObjectRequest(protoDefinitions[0], MessageType, input)
|
||||
.WithProtoFileResolver(resolver);
|
||||
|
||||
try
|
||||
{
|
||||
return await ProtoBufToJsonConverter.ConvertAsync(request, cancellationToken).ConfigureAwait(false);
|
||||
return await ProtoBufToJsonConverter.ConvertAsync(request, cancellationToken);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="ProtoBufJsonConverter" Version="0.10.0" />
|
||||
<PackageReference Include="ProtoBufJsonConverter" Version="0.11.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using WireMock.Net.Testcontainers;
|
||||
|
||||
namespace DotNet.Testcontainers.Configurations;
|
||||
|
||||
internal static class HttpWaitStrategyExtensions
|
||||
{
|
||||
internal static HttpWaitStrategy WithBasicAuthentication(this HttpWaitStrategy strategy, WireMockConfiguration configuration)
|
||||
{
|
||||
if (configuration.HasBasicAuthentication)
|
||||
{
|
||||
return strategy.WithBasicAuthentication(configuration.Username, configuration.Password);
|
||||
}
|
||||
|
||||
return strategy;
|
||||
}
|
||||
}
|
||||
20
src/WireMock.Net.Testcontainers/Utils/CombineUtils.cs
Normal file
20
src/WireMock.Net.Testcontainers/Utils/CombineUtils.cs
Normal file
@@ -0,0 +1,20 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace WireMock.Net.Testcontainers.Utils;
|
||||
|
||||
internal static class CombineUtils
|
||||
{
|
||||
internal static List<T> Combine<T>(List<T> oldValue, List<T> newValue)
|
||||
{
|
||||
return oldValue.Union(newValue).ToList();
|
||||
}
|
||||
|
||||
internal static Dictionary<TKey, TValue> Combine<TKey, TValue>(Dictionary<TKey, TValue> oldValue, Dictionary<TKey, TValue> newValue)
|
||||
where TKey : notnull
|
||||
{
|
||||
return oldValue.Union(newValue).ToDictionary(item => item.Key, item => item.Value);
|
||||
}
|
||||
}
|
||||
@@ -1,12 +1,12 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Docker.DotNet.Models;
|
||||
using DotNet.Testcontainers.Builders;
|
||||
using DotNet.Testcontainers.Configurations;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
using WireMock.Net.Testcontainers.Utils;
|
||||
|
||||
namespace WireMock.Net.Testcontainers;
|
||||
|
||||
@@ -77,8 +77,8 @@ public sealed class WireMockConfiguration : ContainerConfiguration
|
||||
StaticMappingsPath = BuildConfiguration.Combine(oldValue.StaticMappingsPath, newValue.StaticMappingsPath);
|
||||
WatchStaticMappings = BuildConfiguration.Combine(oldValue.WatchStaticMappings, newValue.WatchStaticMappings);
|
||||
WatchStaticMappingsInSubdirectories = BuildConfiguration.Combine(oldValue.WatchStaticMappingsInSubdirectories, newValue.WatchStaticMappingsInSubdirectories);
|
||||
AdditionalUrls = Combine(oldValue.AdditionalUrls, newValue.AdditionalUrls);
|
||||
ProtoDefinitions = Combine(oldValue.ProtoDefinitions, newValue.ProtoDefinitions);
|
||||
AdditionalUrls = CombineUtils.Combine(oldValue.AdditionalUrls, newValue.AdditionalUrls);
|
||||
ProtoDefinitions = CombineUtils.Combine(oldValue.ProtoDefinitions, newValue.ProtoDefinitions);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -130,16 +130,4 @@ public sealed class WireMockConfiguration : ContainerConfiguration
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private static List<T> Combine<T>(List<T> oldValue, List<T> newValue)
|
||||
{
|
||||
return oldValue.Concat(newValue).ToList();
|
||||
}
|
||||
|
||||
private static Dictionary<TKey, TValue> Combine<TKey, TValue>(Dictionary<TKey, TValue> oldValue, Dictionary<TKey, TValue> newValue)
|
||||
{
|
||||
return newValue
|
||||
.Concat(oldValue.Where(item => !newValue.Keys.Contains(item.Key)))
|
||||
.ToDictionary(item => item.Key, item => item.Value);
|
||||
}
|
||||
}
|
||||
@@ -228,6 +228,7 @@ public sealed class WireMockContainer : DockerContainer
|
||||
foreach (var kvp in _configuration.ProtoDefinitions)
|
||||
{
|
||||
Logger.LogInformation("Adding ProtoDefinition {Id}", kvp.Key);
|
||||
|
||||
foreach (var protoDefinition in kvp.Value)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Runtime.InteropServices;
|
||||
using Docker.DotNet.Models;
|
||||
using DotNet.Testcontainers.Builders;
|
||||
@@ -250,6 +252,23 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
||||
|
||||
builder.Validate();
|
||||
|
||||
var waitForContainerOS = _imageOS == OSPlatform.Windows ? Wait.ForWindowsContainer() : Wait.ForUnixContainer();
|
||||
builder
|
||||
.WithWaitStrategy(waitForContainerOS
|
||||
.UntilHttpRequestIsSucceeded(httpWaitStrategy => httpWaitStrategy
|
||||
.ForPort(WireMockContainer.ContainerPort)
|
||||
.WithMethod(HttpMethod.Get)
|
||||
.WithBasicAuthentication(DockerResourceConfiguration)
|
||||
.ForPath("/__admin/health")
|
||||
.ForStatusCode(HttpStatusCode.OK)
|
||||
.ForResponseMessageMatching(async httpResponseMessage =>
|
||||
{
|
||||
var content = await httpResponseMessage.Content.ReadAsStringAsync();
|
||||
return content?.Contains("Healthy") == true;
|
||||
})
|
||||
)
|
||||
);
|
||||
|
||||
return new WireMockContainer(builder.DockerResourceConfiguration);
|
||||
}
|
||||
|
||||
@@ -262,7 +281,9 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
||||
return builder
|
||||
.WithPortBinding(WireMockContainer.ContainerPort, true)
|
||||
.WithCommand($"--WireMockLogger {DefaultLogger}")
|
||||
.WithWaitStrategy(waitForContainerOS.UntilMessageIsLogged("WireMock.Net server running"));
|
||||
.WithWaitStrategy(waitForContainerOS
|
||||
.UntilMessageIsLogged("WireMock.Net server running", waitStrategy => waitStrategy.WithTimeout(TimeSpan.FromSeconds(30)))
|
||||
);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
|
||||
161
test/WireMock.Net.Tests/Testcontainers/CombineUtilsTests.cs
Normal file
161
test/WireMock.Net.Tests/Testcontainers/CombineUtilsTests.cs
Normal file
@@ -0,0 +1,161 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Collections.Generic;
|
||||
using FluentAssertions;
|
||||
using WireMock.Net.Testcontainers.Utils;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Testcontainers;
|
||||
|
||||
public class CombineUtilsTests
|
||||
{
|
||||
[Fact]
|
||||
public void Combine_Lists_WithBothEmpty_ReturnsEmptyList()
|
||||
{
|
||||
// Arrange
|
||||
var oldValue = new List<string>();
|
||||
var newValue = new List<string>();
|
||||
|
||||
// Act
|
||||
var result = CombineUtils.Combine(oldValue, newValue);
|
||||
|
||||
// Assert
|
||||
result.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Combine_Lists_WithEmptyOldValue_ReturnsNewValue()
|
||||
{
|
||||
// Arrange
|
||||
var oldValue = new List<string>();
|
||||
var newValue = new List<string> { "item1", "item2" };
|
||||
|
||||
// Act
|
||||
var result = CombineUtils.Combine(oldValue, newValue);
|
||||
|
||||
// Assert
|
||||
result.Should().Equal("item1", "item2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Combine_Lists_WithEmptyNewValue_ReturnsOldValue()
|
||||
{
|
||||
// Arrange
|
||||
var oldValue = new List<string> { "item1", "item2" };
|
||||
var newValue = new List<string>();
|
||||
|
||||
// Act
|
||||
var result = CombineUtils.Combine(oldValue, newValue);
|
||||
|
||||
// Assert
|
||||
result.Should().Equal("item1", "item2");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Combine_Lists_WithBothPopulated_ReturnsConcatenatedList()
|
||||
{
|
||||
// Arrange
|
||||
var oldValue = new List<int> { 1, 2, 3 };
|
||||
var newValue = new List<int> { 4, 5, 6 };
|
||||
|
||||
// Act
|
||||
var result = CombineUtils.Combine(oldValue, newValue);
|
||||
|
||||
// Assert
|
||||
result.Should().Equal(1, 2, 3, 4, 5, 6);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Combine_Lists_WithDuplicates_RemovesDuplicates()
|
||||
{
|
||||
// Arrange
|
||||
var oldValue = new List<string> { "a", "b", "c" };
|
||||
var newValue = new List<string> { "b", "c", "d" };
|
||||
|
||||
// Act
|
||||
var result = CombineUtils.Combine(oldValue, newValue);
|
||||
|
||||
// Assert
|
||||
result.Should().Equal("a", "b", "c", "d");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Combine_Dictionaries_WithBothEmpty_ReturnsEmptyDictionary()
|
||||
{
|
||||
// Arrange
|
||||
var oldValue = new Dictionary<string, int>();
|
||||
var newValue = new Dictionary<string, int>();
|
||||
|
||||
// Act
|
||||
var result = CombineUtils.Combine(oldValue, newValue);
|
||||
|
||||
// Assert
|
||||
result.Should().BeEmpty();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Combine_Dictionaries_WithEmptyOldValue_ReturnsNewValue()
|
||||
{
|
||||
// Arrange
|
||||
var oldValue = new Dictionary<string, int>();
|
||||
var newValue = new Dictionary<string, int>
|
||||
{
|
||||
{ "key1", 1 },
|
||||
{ "key2", 2 }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = CombineUtils.Combine(oldValue, newValue);
|
||||
|
||||
// Assert
|
||||
result.Should().HaveCount(2);
|
||||
result["key1"].Should().Be(1);
|
||||
result["key2"].Should().Be(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Combine_Dictionaries_WithEmptyNewValue_ReturnsOldValue()
|
||||
{
|
||||
// Arrange
|
||||
var oldValue = new Dictionary<string, int>
|
||||
{
|
||||
{ "key1", 1 },
|
||||
{ "key2", 2 }
|
||||
};
|
||||
var newValue = new Dictionary<string, int>();
|
||||
|
||||
// Act
|
||||
var result = CombineUtils.Combine(oldValue, newValue);
|
||||
|
||||
// Assert
|
||||
result.Should().HaveCount(2);
|
||||
result["key1"].Should().Be(1);
|
||||
result["key2"].Should().Be(2);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Combine_Dictionaries_WithNoOverlappingKeys_ReturnsMergedDictionary()
|
||||
{
|
||||
// Arrange
|
||||
var oldValue = new Dictionary<string, string>
|
||||
{
|
||||
{ "key1", "value1" },
|
||||
{ "key2", "value2" }
|
||||
};
|
||||
var newValue = new Dictionary<string, string>
|
||||
{
|
||||
{ "key3", "value3" },
|
||||
{ "key4", "value4" }
|
||||
};
|
||||
|
||||
// Act
|
||||
var result = CombineUtils.Combine(oldValue, newValue);
|
||||
|
||||
// Assert
|
||||
result.Should().HaveCount(4);
|
||||
result["key1"].Should().Be("value1");
|
||||
result["key2"].Should().Be("value2");
|
||||
result["key3"].Should().Be("value3");
|
||||
result["key4"].Should().Be("value4");
|
||||
}
|
||||
}
|
||||
@@ -19,7 +19,7 @@ using Xunit.Abstractions;
|
||||
|
||||
namespace WireMock.Net.Tests.Testcontainers;
|
||||
|
||||
[Collection("Grpc")]
|
||||
//[Collection("Grpc")]
|
||||
public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
||||
{
|
||||
[Fact]
|
||||
@@ -37,7 +37,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
||||
.WithCommand("--Urls", $"http://*:80 grpc://*:{port}")
|
||||
.WithPortBinding(port, true)
|
||||
.Build();
|
||||
|
||||
|
||||
try
|
||||
{
|
||||
await wireMockContainer.StartAsync();
|
||||
@@ -171,6 +171,35 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
||||
await StopAsync(wireMockContainer);
|
||||
}
|
||||
|
||||
private async Task<HelloReply> When_GrpcClient_Calls_SayHelloAsync(WireMockContainer wireMockContainer)
|
||||
{
|
||||
var address = wireMockContainer.GetPublicUrls().First(x => x.Key != 80).Value;
|
||||
var channel = GrpcChannel.ForAddress(address);
|
||||
|
||||
var client = new Greeter.GreeterClient(channel);
|
||||
|
||||
try
|
||||
{
|
||||
return await client.SayHelloAsync(new HelloRequest { Name = "stef" });
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
testOutputHelper.WriteLine("Exception during GrpcClient Call to {0}. Exception = {1}.", address, ex);
|
||||
|
||||
testOutputHelper.WriteLine("Dumping WireMock.Net logs:");
|
||||
var (stdOut, stdError) = await wireMockContainer.GetLogsAsync(DateTime.MinValue);
|
||||
testOutputHelper.WriteLine("Out :\r\n{0}", stdOut);
|
||||
testOutputHelper.WriteLine("Error:\r\n{0}", stdError);
|
||||
|
||||
testOutputHelper.WriteLine("Dumping WireMock.Net mappings:");
|
||||
using var httpClient = wireMockContainer.CreateClient();
|
||||
using var response = await httpClient.GetAsync("/__admin/mappings");
|
||||
var mappings = await response.Content.ReadAsStringAsync();
|
||||
testOutputHelper.WriteLine("Mappings:\r\n{0}", mappings);
|
||||
throw;
|
||||
}
|
||||
}
|
||||
|
||||
private async Task StopAsync(WireMockContainer wireMockContainer)
|
||||
{
|
||||
try
|
||||
@@ -240,18 +269,6 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
||||
|
||||
var result = await httpClient.PostAsync("/__admin/mappings", new StringContent(mappingsJson, Encoding.UTF8, WireMockConstants.ContentTypeJson));
|
||||
result.EnsureSuccessStatusCode();
|
||||
|
||||
await Task.Delay(5000);
|
||||
}
|
||||
|
||||
private static async Task<HelloReply> When_GrpcClient_Calls_SayHelloAsync(WireMockContainer wireMockContainer)
|
||||
{
|
||||
var address = wireMockContainer.GetPublicUrls().First(x => x.Key != 80).Value;
|
||||
var channel = GrpcChannel.ForAddress(address);
|
||||
|
||||
var client = new Greeter.GreeterClient(channel);
|
||||
|
||||
return await client.SayHelloAsync(new HelloRequest { Name = "stef" });
|
||||
}
|
||||
|
||||
private static void Then_ReplyMessage_Should_BeCorrect(HelloReply reply)
|
||||
|
||||
@@ -38,6 +38,10 @@
|
||||
<Compile Remove="Util\JsonUtilsTests.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\..\src\WireMock.Net.Testcontainers\Utils\CombineUtils.cs" Link="Testcontainers\CombineUtils.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!-- https://stackoverflow.com/questions/59406201/filenesting-not-working-for-class-or-shared-library-projects -->
|
||||
<ProjectCapability Include="ConfigurableFileNesting" />
|
||||
|
||||
Reference in New Issue
Block a user