mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-17 08:56:51 +01:00
Compare commits
23 Commits
1.20.0
...
MappingSer
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5f6f5663e1 | ||
|
|
803e983645 | ||
|
|
c88e7378a7 | ||
|
|
b090296559 | ||
|
|
8f81fb0d96 | ||
|
|
e5afd69f7c | ||
|
|
b4af082586 | ||
|
|
f38133d7a4 | ||
|
|
3011509c51 | ||
|
|
597c95000e | ||
|
|
ad150280fd | ||
|
|
4617b99c30 | ||
|
|
6bb506e1f8 | ||
|
|
ffd4d89946 | ||
|
|
b40fce694d | ||
|
|
79f758fd4d | ||
|
|
aafe2339e4 | ||
|
|
708af55051 | ||
|
|
e6e4138466 | ||
|
|
6cc8c04486 | ||
|
|
dd4770a78b | ||
|
|
de15e0d48e | ||
|
|
f6452d1dce |
@@ -1,3 +1,10 @@
|
|||||||
|
# 1.22.0 (02 January 2026)
|
||||||
|
- [#1412](https://github.com/wiremock/WireMock.Net/pull/1412) - chore(testcontainers): bump up Testcontainers to version 4.10.0 [feature] contributed by [vhatsura](https://github.com/vhatsura)
|
||||||
|
- [#1411](https://github.com/wiremock/WireMock.Net/issues/1411) - WireMock.Net.Testcontainers isn't compatible with Testcontainers 4.10.0 [bug]
|
||||||
|
|
||||||
|
# 1.21.0 (25 December 2025)
|
||||||
|
- [#1408](https://github.com/wiremock/WireMock.Net/pull/1408) - Fix readyness-check for Testcontainers [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|
||||||
# 1.20.0 (24 December 2025)
|
# 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)
|
- [#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)
|
- [#1400](https://github.com/wiremock/WireMock.Net/pull/1400) - Add WireMock.Net.NUnit project [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>1.20.0</VersionPrefix>
|
<VersionPrefix>1.22.0</VersionPrefix>
|
||||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||||
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
||||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
rem https://github.com/StefH/GitHubReleaseNotes
|
rem https://github.com/StefH/GitHubReleaseNotes
|
||||||
|
|
||||||
SET version=1.20.0
|
SET version=1.22.0
|
||||||
|
|
||||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels wontfix test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
|
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels wontfix test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,5 @@
|
|||||||
# 1.20.0 (24 December 2025)
|
# 1.22.0 (02 January 2026)
|
||||||
- #1399 Upgrade RamlToOpenApiConverter and YamlDotNet [feature]
|
- #1412 chore(testcontainers): bump up Testcontainers to version 4.10.0 [feature]
|
||||||
- #1400 Add WireMock.Net.NUnit project [feature]
|
- #1411 WireMock.Net.Testcontainers isn't compatible with Testcontainers 4.10.0 [bug]
|
||||||
- #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
|
The full release notes can be found here: https://github.com/wiremock/WireMock.Net/blob/master/CHANGELOG.md
|
||||||
@@ -100,7 +100,7 @@ jobs:
|
|||||||
- job: Windows_Build_Test
|
- job: Windows_Build_Test
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'windows-2022'
|
vmImage: 'windows-2025'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
@@ -141,7 +141,7 @@ jobs:
|
|||||||
dependsOn: Windows_Build_Test
|
dependsOn: Windows_Build_Test
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'windows-2022'
|
vmImage: 'windows-2025'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- script: |
|
- script: |
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
pool:
|
pool:
|
||||||
vmImage: 'windows-2022'
|
vmImage: 'windows-2025'
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
Prerelease: ''
|
Prerelease: ''
|
||||||
|
|||||||
@@ -32,7 +32,7 @@ public class ResponseModel
|
|||||||
public object? BodyAsJson { get; set; }
|
public object? BodyAsJson { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
|
/// Gets or sets a value indicating whether the Json Body String needs to be indented.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? BodyAsJsonIndented { get; set; }
|
public bool? BodyAsJsonIndented { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@ public interface IBodyData
|
|||||||
object? BodyAsJson { get; set; }
|
object? BodyAsJson { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
|
/// Gets or sets a value indicating whether the Json Body String needs to be indented.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool? BodyAsJsonIndented { get; set; }
|
bool? BodyAsJsonIndented { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>WireMock.Net.Routing extends WireMock.Net with modern, minimal-API-style routing for .NET</Description>
|
<Description>WireMock.Net.Routing extends WireMock.Net with modern, minimal-API-style routing for .NET</Description>
|
||||||
<Authors>Gennadii Saltyshchak</Authors>
|
<Authors>Gennadii Saltyshchak</Authors>
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.7.0" />
|
<PackageReference Include="JsonConverter.Abstractions" Version="0.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -3,7 +3,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
@@ -164,8 +163,8 @@ public class MappingBuilder : IMappingBuilder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ToJson(object value)
|
private string ToJson(object value)
|
||||||
{
|
{
|
||||||
return JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsDefault);
|
return _settings.DefaultJsonSerializer.Serialize(value, JsonSerializationConstants.JsonConverterOptionsDefault);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
49
src/WireMock.Net.Minimal/Serialization/MappingSerializer.cs
Normal file
49
src/WireMock.Net.Minimal/Serialization/MappingSerializer.cs
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using JsonConverter.Abstractions;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
#if NETSTANDARD2_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER || NET6_0_OR_GREATER || NET461
|
||||||
|
using System.Text.Json;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace WireMock.Serialization;
|
||||||
|
|
||||||
|
internal class MappingSerializer(IJsonConverter jsonConverter)
|
||||||
|
{
|
||||||
|
internal T[] DeserializeJsonToArray<T>(string value)
|
||||||
|
{
|
||||||
|
return DeserializeObjectToArray<T>(jsonConverter.Deserialize<object>(value)!);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static T[] DeserializeObjectToArray<T>(object value)
|
||||||
|
{
|
||||||
|
if (value is JArray jArray)
|
||||||
|
{
|
||||||
|
return jArray.ToObject<T[]>()!;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value is JObject jObject)
|
||||||
|
{
|
||||||
|
var singleResult = jObject.ToObject<T>();
|
||||||
|
return [singleResult!];
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NETSTANDARD2_0_OR_GREATER || NETCOREAPP3_1_OR_GREATER || NET6_0_OR_GREATER || NET461
|
||||||
|
if (value is JsonElement jElement)
|
||||||
|
{
|
||||||
|
if (jElement.ValueKind == JsonValueKind.Array)
|
||||||
|
{
|
||||||
|
return jElement.Deserialize<T[]>()!;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (jElement.ValueKind == JsonValueKind.Object)
|
||||||
|
{
|
||||||
|
var singleResult = jElement.Deserialize<T>();
|
||||||
|
return [singleResult!];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
throw new InvalidOperationException("Cannot deserialize the provided value to an array or object.");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,7 +2,8 @@
|
|||||||
|
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Newtonsoft.Json;
|
using JsonConverter.Abstractions;
|
||||||
|
using JsonConverter.Newtonsoft.Json;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
|
|
||||||
@@ -12,12 +13,15 @@ internal class MappingToFileSaver
|
|||||||
{
|
{
|
||||||
private readonly WireMockServerSettings _settings;
|
private readonly WireMockServerSettings _settings;
|
||||||
private readonly MappingConverter _mappingConverter;
|
private readonly MappingConverter _mappingConverter;
|
||||||
|
private readonly IJsonConverter _jsonConverter;
|
||||||
private readonly MappingFileNameSanitizer _fileNameSanitizer;
|
private readonly MappingFileNameSanitizer _fileNameSanitizer;
|
||||||
|
|
||||||
public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter)
|
public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter)
|
||||||
{
|
{
|
||||||
_settings = Guard.NotNull(settings);
|
_settings = Guard.NotNull(settings);
|
||||||
_mappingConverter = Guard.NotNull(mappingConverter);
|
_mappingConverter = Guard.NotNull(mappingConverter);
|
||||||
|
|
||||||
|
_jsonConverter = settings.DefaultJsonSerializer ?? new NewtonsoftJsonConverter();
|
||||||
_fileNameSanitizer = new MappingFileNameSanitizer(settings);
|
_fileNameSanitizer = new MappingFileNameSanitizer(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,6 +60,8 @@ internal class MappingToFileSaver
|
|||||||
{
|
{
|
||||||
_settings.Logger.Info("Saving Mapping file {0}", path);
|
_settings.Logger.Info("Saving Mapping file {0}", path);
|
||||||
|
|
||||||
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsDefault));
|
var json = _jsonConverter.Serialize(value, JsonSerializationConstants.JsonConverterOptionsDefault);
|
||||||
|
|
||||||
|
_settings.FileSystemHandler.WriteMappingFile(path, json);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -7,7 +7,7 @@ using System.Linq;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Newtonsoft.Json;
|
using JsonConverter.Abstractions;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
@@ -236,7 +236,7 @@ public partial class WireMockServer
|
|||||||
|
|
||||||
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_settings.FileSystemHandler, path, out var value))
|
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_settings.FileSystemHandler, path, out var value))
|
||||||
{
|
{
|
||||||
var mappingModels = DeserializeJsonToArray<MappingModel>(value);
|
var mappingModels = _mappingSerializer.DeserializeJsonToArray<MappingModel>(value);
|
||||||
if (mappingModels.Length == 1 && Guid.TryParse(filenameWithoutExtension, out var guidFromFilename))
|
if (mappingModels.Length == 1 && Guid.TryParse(filenameWithoutExtension, out var guidFromFilename))
|
||||||
{
|
{
|
||||||
ConvertMappingAndRegisterAsRespondProvider(mappingModels[0], guidFromFilename, path);
|
ConvertMappingAndRegisterAsRespondProvider(mappingModels[0], guidFromFilename, path);
|
||||||
@@ -826,25 +826,31 @@ public partial class WireMockServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Encoding? ToEncoding(EncodingModel? encodingModel)
|
private ResponseMessage ToJson<T>(T result, bool keepNullValues = false, object? statusCode = null)
|
||||||
{
|
{
|
||||||
return encodingModel != null ? Encoding.GetEncoding(encodingModel.CodePage) : null;
|
var jsonOptions = new JsonConverterOptions
|
||||||
}
|
{
|
||||||
|
WriteIndented = true,
|
||||||
|
IgnoreNullValues = !keepNullValues
|
||||||
|
};
|
||||||
|
|
||||||
private static ResponseMessage ToJson<T>(T result, bool keepNullValues = false, object? statusCode = null)
|
|
||||||
{
|
|
||||||
return new ResponseMessage
|
return new ResponseMessage
|
||||||
{
|
{
|
||||||
BodyData = new BodyData
|
BodyData = new BodyData
|
||||||
{
|
{
|
||||||
DetectedBodyType = BodyType.String,
|
DetectedBodyType = BodyType.String,
|
||||||
BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? JsonSerializationConstants.JsonSerializerSettingsIncludeNullValues : JsonSerializationConstants.JsonSerializerSettingsDefault)
|
BodyAsString = _settings.DefaultJsonSerializer.Serialize(result!, jsonOptions)
|
||||||
},
|
},
|
||||||
StatusCode = statusCode ?? (int)HttpStatusCode.OK,
|
StatusCode = statusCode ?? (int)HttpStatusCode.OK,
|
||||||
Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(WireMockConstants.ContentTypeJson) } }
|
Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(WireMockConstants.ContentTypeJson) } }
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Encoding? ToEncoding(EncodingModel? encodingModel)
|
||||||
|
{
|
||||||
|
return encodingModel != null ? Encoding.GetEncoding(encodingModel.CodePage) : null;
|
||||||
|
}
|
||||||
|
|
||||||
private static ResponseMessage ToResponseMessage(string text)
|
private static ResponseMessage ToResponseMessage(string text)
|
||||||
{
|
{
|
||||||
return new ResponseMessage
|
return new ResponseMessage
|
||||||
@@ -859,6 +865,18 @@ public partial class WireMockServer
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static T[] DeserializeRequestMessageToArray<T>(IRequestMessage requestMessage)
|
||||||
|
{
|
||||||
|
if (requestMessage.BodyData?.DetectedBodyType == BodyType.Json && requestMessage.BodyData.BodyAsJson != null)
|
||||||
|
{
|
||||||
|
var bodyAsJson = requestMessage.BodyData.BodyAsJson!;
|
||||||
|
|
||||||
|
return MappingSerializer.DeserializeObjectToArray<T>(bodyAsJson);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new NotSupportedException();
|
||||||
|
}
|
||||||
|
|
||||||
private static T DeserializeObject<T>(IRequestMessage requestMessage) where T : new()
|
private static T DeserializeObject<T>(IRequestMessage requestMessage) where T : new()
|
||||||
{
|
{
|
||||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||||
@@ -874,32 +892,4 @@ public partial class WireMockServer
|
|||||||
throw new NotSupportedException();
|
throw new NotSupportedException();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static T[] DeserializeRequestMessageToArray<T>(IRequestMessage requestMessage)
|
|
||||||
{
|
|
||||||
if (requestMessage.BodyData?.DetectedBodyType == BodyType.Json && requestMessage.BodyData.BodyAsJson != null)
|
|
||||||
{
|
|
||||||
var bodyAsJson = requestMessage.BodyData.BodyAsJson;
|
|
||||||
|
|
||||||
return DeserializeObjectToArray<T>(bodyAsJson);
|
|
||||||
}
|
|
||||||
|
|
||||||
throw new NotSupportedException();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static T[] DeserializeJsonToArray<T>(string value)
|
|
||||||
{
|
|
||||||
return DeserializeObjectToArray<T>(JsonUtils.DeserializeObject(value));
|
|
||||||
}
|
|
||||||
|
|
||||||
private static T[] DeserializeObjectToArray<T>(object value)
|
|
||||||
{
|
|
||||||
if (value is JArray jArray)
|
|
||||||
{
|
|
||||||
return jArray.ToObject<T[]>()!;
|
|
||||||
}
|
|
||||||
|
|
||||||
var singleResult = ((JObject)value).ToObject<T>();
|
|
||||||
return new[] { singleResult! };
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ public partial class WireMockServer
|
|||||||
|
|
||||||
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_settings.FileSystemHandler, path, out var value))
|
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_settings.FileSystemHandler, path, out var value))
|
||||||
{
|
{
|
||||||
var mappings = DeserializeJsonToArray<OrgMapping>(value);
|
var mappings = _mappingSerializer.DeserializeJsonToArray<OrgMapping>(value);
|
||||||
foreach (var mapping in mappings)
|
foreach (var mapping in mappings)
|
||||||
{
|
{
|
||||||
if (mappings.Length == 1 && Guid.TryParse(filenameWithoutExtension, out var guidFromFilename))
|
if (mappings.Length == 1 && Guid.TryParse(filenameWithoutExtension, out var guidFromFilename))
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using System.Net.Http;
|
|||||||
using System.Threading;
|
using System.Threading;
|
||||||
using AnyOfTypes;
|
using AnyOfTypes;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using JsonConverter.Newtonsoft.Json;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
@@ -47,6 +48,7 @@ public partial class WireMockServer : IWireMockServer
|
|||||||
private readonly MappingBuilder _mappingBuilder;
|
private readonly MappingBuilder _mappingBuilder;
|
||||||
private readonly IGuidUtils _guidUtils = new GuidUtils();
|
private readonly IGuidUtils _guidUtils = new GuidUtils();
|
||||||
private readonly IDateTimeUtils _dateTimeUtils = new DateTimeUtils();
|
private readonly IDateTimeUtils _dateTimeUtils = new DateTimeUtils();
|
||||||
|
private readonly MappingSerializer _mappingSerializer;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
@@ -357,6 +359,8 @@ public partial class WireMockServer : IWireMockServer
|
|||||||
{
|
{
|
||||||
_settings = Guard.NotNull(settings);
|
_settings = Guard.NotNull(settings);
|
||||||
|
|
||||||
|
_mappingSerializer = new MappingSerializer(settings.DefaultJsonSerializer ?? new NewtonsoftJsonConverter());
|
||||||
|
|
||||||
// Set default values if not provided
|
// Set default values if not provided
|
||||||
_settings.Logger = settings.Logger ?? new WireMockNullLogger();
|
_settings.Logger = settings.Logger ?? new WireMockNullLogger();
|
||||||
_settings.FileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
|
_settings.FileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
|
||||||
@@ -639,7 +643,7 @@ public partial class WireMockServer : IWireMockServer
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public IWireMockServer WithMapping(string mappings)
|
public IWireMockServer WithMapping(string mappings)
|
||||||
{
|
{
|
||||||
var mappingModels = DeserializeJsonToArray<MappingModel>(mappings);
|
var mappingModels = _mappingSerializer.DeserializeJsonToArray<MappingModel>(mappings);
|
||||||
foreach (var mappingModel in mappingModels)
|
foreach (var mappingModel in mappingModels)
|
||||||
{
|
{
|
||||||
ConvertMappingAndRegisterAsRespondProvider(mappingModel, mappingModel.Guid ?? Guid.NewGuid());
|
ConvertMappingAndRegisterAsRespondProvider(mappingModel, mappingModel.Guid ?? Guid.NewGuid());
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Minimal version from the lightweight Http Mocking Server for .NET</Description>
|
<Description>Minimal version from the lightweight Http Mocking Server for .NET</Description>
|
||||||
<AssemblyTitle>WireMock.Net.Minimal</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.Minimal</AssemblyTitle>
|
||||||
@@ -57,8 +57,8 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JsonConverter.Abstractions" Version="0.7.0" />
|
<!--<PackageReference Include="JsonConverter.Abstractions" Version="0.8.0" />-->
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<!--<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />-->
|
||||||
<PackageReference Include="NJsonSchema.Extensions" Version="0.1.0" />
|
<PackageReference Include="NJsonSchema.Extensions" Version="0.1.0" />
|
||||||
<PackageReference Include="NSwag.Core" Version="13.16.1" />
|
<PackageReference Include="NSwag.Core" Version="13.16.1" />
|
||||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||||
@@ -118,11 +118,13 @@
|
|||||||
|
|
||||||
<!-- https://github.com/wiremock/WireMock.Net/issues/507 -->
|
<!-- https://github.com/wiremock/WireMock.Net/issues/507 -->
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
|
<PackageReference Include="Microsoft.AspNetCore.Server.IIS" Version="2.2.6" />
|
||||||
|
<PackageReference Include="JsonConverter.System.Text.Json" Version="0.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
|
||||||
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
<FrameworkReference Include="Microsoft.AspNetCore.App" />
|
||||||
<PackageReference Include="Scriban.Signed" Version="5.5.0" />
|
<PackageReference Include="Scriban.Signed" Version="5.5.0" />
|
||||||
|
<PackageReference Include="JsonConverter.System.Text.Json" Version="0.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.7.0" />
|
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />
|
||||||
<PackageReference Include="RestEase" Version="1.6.4" />
|
<PackageReference Include="RestEase" Version="1.6.4" />
|
||||||
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using JsonConverter.Abstractions;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Serialization;
|
using Newtonsoft.Json.Serialization;
|
||||||
|
|
||||||
@@ -7,24 +8,30 @@ namespace WireMock.Serialization;
|
|||||||
|
|
||||||
internal static class JsonSerializationConstants
|
internal static class JsonSerializationConstants
|
||||||
{
|
{
|
||||||
public static readonly JsonSerializerSettings JsonSerializerSettingsDefault = new()
|
internal static readonly JsonConverterOptions JsonConverterOptionsDefault = new()
|
||||||
{
|
{
|
||||||
Formatting = Formatting.Indented,
|
WriteIndented = true,
|
||||||
NullValueHandling = NullValueHandling.Ignore
|
IgnoreNullValues = true
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly JsonSerializerSettings JsonSerializerSettingsIncludeNullValues = new()
|
//internal static readonly JsonSerializerSettings JsonSerializerSettingsDefault = new()
|
||||||
|
//{
|
||||||
|
// Formatting = Formatting.Indented,
|
||||||
|
// NullValueHandling = NullValueHandling.Ignore
|
||||||
|
//};
|
||||||
|
|
||||||
|
internal static readonly JsonSerializerSettings JsonSerializerSettingsIncludeNullValues = new()
|
||||||
{
|
{
|
||||||
Formatting = Formatting.Indented,
|
Formatting = Formatting.Indented,
|
||||||
NullValueHandling = NullValueHandling.Include
|
NullValueHandling = NullValueHandling.Include
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly JsonSerializerSettings JsonDeserializerSettingsWithDateParsingNone = new()
|
internal static readonly JsonSerializerSettings JsonDeserializerSettingsWithDateParsingNone = new()
|
||||||
{
|
{
|
||||||
DateParseHandling = DateParseHandling.None
|
DateParseHandling = DateParseHandling.None
|
||||||
};
|
};
|
||||||
|
|
||||||
public static readonly JsonSerializerSettings JsonSerializerSettingsPact = new()
|
internal static readonly JsonSerializerSettings JsonSerializerSettingsPact = new()
|
||||||
{
|
{
|
||||||
Formatting = Formatting.Indented,
|
Formatting = Formatting.Indented,
|
||||||
NullValueHandling = NullValueHandling.Ignore,
|
NullValueHandling = NullValueHandling.Ignore,
|
||||||
|
|||||||
@@ -14,6 +14,8 @@ using WireMock.RegularExpressions;
|
|||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using WireMock.Models;
|
using WireMock.Models;
|
||||||
|
using JsonConverter.Abstractions;
|
||||||
|
using JsonConverter.Newtonsoft.Json;
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
@@ -338,4 +340,14 @@ public class WireMockServerSettings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public HandlebarsSettings? HandlebarsSettings { get; set; }
|
public HandlebarsSettings? HandlebarsSettings { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the default JSON converter used for serialization.
|
||||||
|
/// </summary>
|
||||||
|
/// <remarks>
|
||||||
|
/// Set this property to customize how objects are serialized to and deserialized from JSON during mapping.
|
||||||
|
/// Default is <see cref="NewtonsoftJsonConverter"/>.
|
||||||
|
/// </remarks>
|
||||||
|
[PublicAPI]
|
||||||
|
public IJsonConverter DefaultJsonSerializer { get; set; } = new NewtonsoftJsonConverter();
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Shared interfaces, models, enumerations and types.</Description>
|
<Description>Shared interfaces, models, enumerations and types.</Description>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<Authors>Stef Heyenrath</Authors>
|
||||||
@@ -48,9 +48,10 @@
|
|||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
||||||
<PackageReference Include="AnyOf" Version="0.4.0" />
|
<PackageReference Include="AnyOf" Version="0.4.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<!--<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />-->
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.1.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.1.0" />
|
||||||
<PackageReference Include="JsonConverter.Abstractions" Version="0.7.0" />
|
<!--<PackageReference Include="JsonConverter.Abstractions" Version="0.8.0" />-->
|
||||||
|
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
||||||
<PackageReference Include="Testcontainers" Version="4.8.0" />
|
<PackageReference Include="Testcontainers" Version="4.10.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -24,28 +24,21 @@ namespace WireMock.Net.Testcontainers;
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// A container for running WireMock in a docker environment.
|
/// A container for running WireMock in a docker environment.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class WireMockContainer : DockerContainer
|
/// <remarks>
|
||||||
|
/// Initializes a new instance of the <see cref="WireMockContainer" /> class.
|
||||||
|
/// </remarks>
|
||||||
|
/// <param name="configuration">The container configuration.</param>
|
||||||
|
public sealed class WireMockContainer(WireMockConfiguration configuration) : DockerContainer(configuration)
|
||||||
{
|
{
|
||||||
private const int EnhancedFileSystemWatcherTimeoutMs = 2000;
|
private const int EnhancedFileSystemWatcherTimeoutMs = 2000;
|
||||||
internal const int ContainerPort = 80;
|
internal const int ContainerPort = 80;
|
||||||
|
|
||||||
private readonly WireMockConfiguration _configuration;
|
private readonly WireMockConfiguration _configuration = Guard.NotNull(configuration);
|
||||||
|
|
||||||
private IWireMockAdminApi? _adminApi;
|
private IWireMockAdminApi? _adminApi;
|
||||||
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
||||||
private IDictionary<int, Uri>? _publicUris;
|
private IDictionary<int, Uri>? _publicUris;
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="WireMockContainer" /> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="configuration">The container configuration.</param>
|
|
||||||
public WireMockContainer(WireMockConfiguration configuration) : base(configuration)
|
|
||||||
{
|
|
||||||
_configuration = Guard.NotNull(configuration);
|
|
||||||
|
|
||||||
Started += async (sender, eventArgs) => await WireMockContainerStartedAsync(sender, eventArgs);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the public Url.
|
/// Gets the public Url.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -157,14 +150,28 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await _adminApi.ReloadStaticMappingsAsync(cancellationToken);
|
var result = await _adminApi.ReloadStaticMappingsAsync(cancellationToken);
|
||||||
Logger.LogInformation("ReloadStaticMappings result: {Result}", result);
|
Logger.LogInformation("WireMock.Net -> ReloadStaticMappings result: {Result}", result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogWarning(ex, "Error calling /__admin/mappings/reloadStaticMappings");
|
Logger.LogWarning(ex, "WireMock.Net -> Error calling /__admin/mappings/reloadStaticMappings");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Performs additional actions after the container is ready.
|
||||||
|
/// </summary>
|
||||||
|
public Task CallAdditionalActionsAfterReadyAsync()
|
||||||
|
{
|
||||||
|
Logger.LogInformation("WireMock.Net -> Calling additional actions.");
|
||||||
|
|
||||||
|
_adminApi = CreateWireMockAdminClient();
|
||||||
|
|
||||||
|
RegisterEnhancedFileSystemWatcher();
|
||||||
|
|
||||||
|
return AddProtoDefinitionsAsync();
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
protected override ValueTask DisposeAsyncCore()
|
protected override ValueTask DisposeAsyncCore()
|
||||||
{
|
{
|
||||||
@@ -197,15 +204,6 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task WireMockContainerStartedAsync(object sender, EventArgs e)
|
|
||||||
{
|
|
||||||
_adminApi = CreateWireMockAdminClient();
|
|
||||||
|
|
||||||
RegisterEnhancedFileSystemWatcher();
|
|
||||||
|
|
||||||
await CallAdditionalActionsAfterStartedAsync();
|
|
||||||
}
|
|
||||||
|
|
||||||
private void RegisterEnhancedFileSystemWatcher()
|
private void RegisterEnhancedFileSystemWatcher()
|
||||||
{
|
{
|
||||||
if (!_configuration.WatchStaticMappings || string.IsNullOrEmpty(_configuration.StaticMappingsPath))
|
if (!_configuration.WatchStaticMappings || string.IsNullOrEmpty(_configuration.StaticMappingsPath))
|
||||||
@@ -223,22 +221,22 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
_enhancedFileSystemWatcher.EnableRaisingEvents = true;
|
_enhancedFileSystemWatcher.EnableRaisingEvents = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task CallAdditionalActionsAfterStartedAsync()
|
private async Task AddProtoDefinitionsAsync()
|
||||||
{
|
{
|
||||||
foreach (var kvp in _configuration.ProtoDefinitions)
|
foreach (var kvp in _configuration.ProtoDefinitions)
|
||||||
{
|
{
|
||||||
Logger.LogInformation("Adding ProtoDefinition {Id}", kvp.Key);
|
Logger.LogInformation("WireMock.Net -> Adding ProtoDefinition '{Id}'", kvp.Key);
|
||||||
|
|
||||||
foreach (var protoDefinition in kvp.Value)
|
foreach (var protoDefinition in kvp.Value)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
var result = await _adminApi!.AddProtoDefinitionAsync(kvp.Key, protoDefinition);
|
var result = await _adminApi!.AddProtoDefinitionAsync(kvp.Key, protoDefinition);
|
||||||
Logger.LogInformation("AddProtoDefinition '{Id}' result: {Result}", kvp.Key, result);
|
Logger.LogInformation("WireMock.Net -> AddProtoDefinition '{Id}' result: {Result}", kvp.Key, result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogWarning(ex, "Error adding ProtoDefinition '{Id}'.", kvp.Key);
|
Logger.LogWarning(ex, "WireMock.Net -> Error adding ProtoDefinition '{Id}'.", kvp.Key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -255,17 +253,17 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ReloadStaticMappingsAsync(args.FullPath);
|
await ReloadStaticMappingsAsync(args.FullPath);
|
||||||
Logger.LogInformation("ReloadStaticMappings triggered from file change: '{FullPath}'.", args.FullPath);
|
Logger.LogInformation("WireMock.Net -> ReloadStaticMappings triggered from file change: '{FullPath}'.", args.FullPath);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
Logger.LogWarning(ex, "Error reloading static mappings from '{FullPath}'.", args.FullPath);
|
Logger.LogWarning(ex, "WireMock.Net -> Error reloading static mappings from '{FullPath}'.", args.FullPath);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ReloadStaticMappingsAsync(string path, CancellationToken cancellationToken = default)
|
private async Task ReloadStaticMappingsAsync(string path, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
Logger.LogInformation("MappingFile created, changed or deleted: '{Path}'. Triggering ReloadStaticMappings.", path);
|
Logger.LogInformation("WireMock.Net -> MappingFile created, changed or deleted: '{Path}'. Triggering ReloadStaticMappings.", path);
|
||||||
await ReloadStaticMappingsAsync(cancellationToken);
|
await ReloadStaticMappingsAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -253,8 +253,9 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
builder.Validate();
|
builder.Validate();
|
||||||
|
|
||||||
var waitForContainerOS = _imageOS == OSPlatform.Windows ? Wait.ForWindowsContainer() : Wait.ForUnixContainer();
|
var waitForContainerOS = _imageOS == OSPlatform.Windows ? Wait.ForWindowsContainer() : Wait.ForUnixContainer();
|
||||||
builder
|
builder = builder
|
||||||
.WithWaitStrategy(waitForContainerOS
|
.WithWaitStrategy(waitForContainerOS
|
||||||
|
.UntilMessageIsLogged("WireMock.Net server running", waitStrategy => waitStrategy.WithTimeout(TimeSpan.FromSeconds(30)))
|
||||||
.UntilHttpRequestIsSucceeded(httpWaitStrategy => httpWaitStrategy
|
.UntilHttpRequestIsSucceeded(httpWaitStrategy => httpWaitStrategy
|
||||||
.ForPort(WireMockContainer.ContainerPort)
|
.ForPort(WireMockContainer.ContainerPort)
|
||||||
.WithMethod(HttpMethod.Get)
|
.WithMethod(HttpMethod.Get)
|
||||||
@@ -267,6 +268,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
return content?.Contains("Healthy") == true;
|
return content?.Contains("Healthy") == true;
|
||||||
})
|
})
|
||||||
)
|
)
|
||||||
|
.AddCustomWaitStrategy(new WireMockWaitStrategy())
|
||||||
);
|
);
|
||||||
|
|
||||||
return new WireMockContainer(builder.DockerResourceConfiguration);
|
return new WireMockContainer(builder.DockerResourceConfiguration);
|
||||||
@@ -277,13 +279,9 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
{
|
{
|
||||||
var builder = base.Init();
|
var builder = base.Init();
|
||||||
|
|
||||||
var waitForContainerOS = _imageOS == OSPlatform.Windows ? Wait.ForWindowsContainer() : Wait.ForUnixContainer();
|
|
||||||
return builder
|
return builder
|
||||||
.WithPortBinding(WireMockContainer.ContainerPort, true)
|
.WithPortBinding(WireMockContainer.ContainerPort, true)
|
||||||
.WithCommand($"--WireMockLogger {DefaultLogger}")
|
.WithCommand($"--WireMockLogger {DefaultLogger}");
|
||||||
.WithWaitStrategy(waitForContainerOS
|
|
||||||
.UntilMessageIsLogged("WireMock.Net server running", waitStrategy => waitStrategy.WithTimeout(TimeSpan.FromSeconds(30)))
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
23
src/WireMock.Net.Testcontainers/WireMockWaitStrategy.cs
Normal file
23
src/WireMock.Net.Testcontainers/WireMockWaitStrategy.cs
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using DotNet.Testcontainers.Configurations;
|
||||||
|
using DotNet.Testcontainers.Containers;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Testcontainers;
|
||||||
|
|
||||||
|
internal class WireMockWaitStrategy : IWaitUntil
|
||||||
|
{
|
||||||
|
public async Task<bool> UntilAsync(IContainer container)
|
||||||
|
{
|
||||||
|
if (container is not WireMockContainer wireMockContainer)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException("The passed container is not a WireMockContainer.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
await wireMockContainer.CallAdditionalActionsAfterReadyAsync();
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ using System;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
|
using JsonConverter.Newtonsoft.Json;
|
||||||
using Moq;
|
using Moq;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using NFluent;
|
using NFluent;
|
||||||
@@ -316,12 +317,11 @@ public class ResponseWithBodyTests
|
|||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request1, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request1, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
Check.That(response.Message.StatusCode).IsEqualTo(200);
|
Check.That(response.Message.StatusCode).IsEqualTo(200);
|
||||||
Check.That(response.Message.BodyData.BodyAsString).Contains("File deleted.");
|
Check.That(response.Message.BodyData?.BodyAsString).Contains("File deleted.");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !(NET451 || NET452)
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task Response_ProvideResponse_WithBody_IJsonConverter_SystemTextJson()
|
public async Task Response_ProvideResponse_WithBody_NewtonsoftJsonConverter()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var requestBody = new BodyData
|
var requestBody = new BodyData
|
||||||
@@ -331,13 +331,34 @@ public class ResponseWithBodyTests
|
|||||||
};
|
};
|
||||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, requestBody);
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, requestBody);
|
||||||
|
|
||||||
var responseBuilder = Response.Create().WithBody(new { foo = "bar", n = 42 }, new JsonConverter.System.Text.Json.SystemTextJsonConverter());
|
var responseBuilder = Response.Create().WithBody(new { foo = "< > & ' 😀 👍 ❤️", n = 42 }, new NewtonsoftJsonConverter());
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
response.Message.BodyData!.BodyAsString.Should().Be(@"{""foo"":""bar"",""n"":42}");
|
response.Message.BodyData!.BodyAsString.Should().Be("""{"foo":"< > & ' 😀 👍 ❤️","n":42}""");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if !(NET451 || NET452 || NET461)
|
||||||
|
[Fact]
|
||||||
|
public async Task Response_ProvideResponse_WithBody_SystemTextJsonConverter()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var requestBody = new BodyData
|
||||||
|
{
|
||||||
|
DetectedBodyType = BodyType.String,
|
||||||
|
BodyAsString = "abc"
|
||||||
|
};
|
||||||
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, requestBody);
|
||||||
|
|
||||||
|
var responseBuilder = Response.Create().WithBody(new { foo = "< > & ' 😀 👍 ❤️", n = 42 }, new JsonConverter.System.Text.Json.SystemTextJsonConverter());
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var response = await responseBuilder.ProvideResponseAsync(_mappingMock.Object, request, _settings).ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
response.Message.BodyData!.BodyAsString.Should().Be("""{"foo":"\u003C \u003E \u0026 \u0027 \uD83D\uDE00 \uD83D\uDC4D \u2764\uFE0F","n":42}""");
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
326
test/WireMock.Net.Tests/Serialization/MappingSerializerTests.cs
Normal file
326
test/WireMock.Net.Tests/Serialization/MappingSerializerTests.cs
Normal file
@@ -0,0 +1,326 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using FluentAssertions;
|
||||||
|
using JsonConverter.Newtonsoft.Json;
|
||||||
|
using WireMock.Admin.Mappings;
|
||||||
|
using WireMock.Serialization;
|
||||||
|
using Xunit;
|
||||||
|
#if NET8_0_OR_GREATER
|
||||||
|
using JsonConverter.System.Text.Json;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
namespace WireMock.Net.Tests.Serialization;
|
||||||
|
|
||||||
|
public class MappingSerializerTests
|
||||||
|
{
|
||||||
|
private const string SingleMappingJson =
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"Guid": "12345678-1234-1234-1234-123456789012",
|
||||||
|
"Priority": 1,
|
||||||
|
"Request": {
|
||||||
|
"Path": "/test"
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 200
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
private const string ArrayMappingJson =
|
||||||
|
"""
|
||||||
|
[
|
||||||
|
{
|
||||||
|
"Guid": "12345678-1234-1234-1234-123456789012",
|
||||||
|
"Priority": 1,
|
||||||
|
"Request": {
|
||||||
|
"Path": "/test1"
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 200
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Guid": "87654321-4321-4321-4321-210987654321",
|
||||||
|
"Priority": 2,
|
||||||
|
"Request": {
|
||||||
|
"Path": "/test2"
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 404
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
""";
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithNewtonsoftJson_SingleObject_ShouldReturnArray()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(SingleMappingJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Should().HaveCount(1);
|
||||||
|
result[0].Guid.Should().Be(Guid.Parse("12345678-1234-1234-1234-123456789012"));
|
||||||
|
result[0].Priority.Should().Be(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithNewtonsoftJson_Array_ShouldReturnArray()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(ArrayMappingJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Should().HaveCount(2);
|
||||||
|
result[0].Guid.Should().Be(Guid.Parse("12345678-1234-1234-1234-123456789012"));
|
||||||
|
result[0].Priority.Should().Be(1);
|
||||||
|
result[1].Guid.Should().Be(Guid.Parse("87654321-4321-4321-4321-210987654321"));
|
||||||
|
result[1].Priority.Should().Be(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithNewtonsoftJson_EmptyArray_ShouldReturnEmptyArray()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var emptyArrayJson = "[]";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(emptyArrayJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithNewtonsoftJson_InvalidJson_ShouldThrowException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var invalidJson = "not valid json";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Action act = () => serializer.DeserializeJsonToArray<MappingModel>(invalidJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<Exception>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithNewtonsoftJson_ComplexMapping_ShouldDeserializeCorrectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var complexJson =
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"Guid": "12345678-1234-1234-1234-123456789012",
|
||||||
|
"Title": "Test Mapping",
|
||||||
|
"Description": "A test mapping",
|
||||||
|
"Priority": 10,
|
||||||
|
"Request": {
|
||||||
|
"Path": "/api/test",
|
||||||
|
"Methods": ["GET", "POST"]
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 201,
|
||||||
|
"Body": "Test Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(complexJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Should().HaveCount(1);
|
||||||
|
result[0].Guid.Should().Be(Guid.Parse("12345678-1234-1234-1234-123456789012"));
|
||||||
|
result[0].Title.Should().Be("Test Mapping");
|
||||||
|
result[0].Description.Should().Be("A test mapping");
|
||||||
|
result[0].Priority.Should().Be(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithNewtonsoftJson_NullValue_ShouldThrowException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var nullJson = "null";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Action act = () => serializer.DeserializeJsonToArray<MappingModel>(nullJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<Exception>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithNewtonsoftJson_PrimitiveValue_ShouldThrowInvalidOperationException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var primitiveJson = "\"string value\"";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Action act = () => serializer.DeserializeJsonToArray<MappingModel>(primitiveJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<InvalidOperationException>()
|
||||||
|
.WithMessage("Cannot deserialize the provided value to an array or object.");
|
||||||
|
}
|
||||||
|
|
||||||
|
#if NET8_0_OR_GREATER
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithSystemTextJson_SingleObject_ShouldReturnArray()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new SystemTextJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(SingleMappingJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Should().HaveCount(1);
|
||||||
|
result[0].Guid.Should().Be(Guid.Parse("12345678-1234-1234-1234-123456789012"));
|
||||||
|
result[0].Priority.Should().Be(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithSystemTextJson_Array_ShouldReturnArray()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new SystemTextJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(ArrayMappingJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Should().HaveCount(2);
|
||||||
|
result[0].Guid.Should().Be(Guid.Parse("12345678-1234-1234-1234-123456789012"));
|
||||||
|
result[0].Priority.Should().Be(1);
|
||||||
|
result[1].Guid.Should().Be(Guid.Parse("87654321-4321-4321-4321-210987654321"));
|
||||||
|
result[1].Priority.Should().Be(2);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithSystemTextJson_EmptyArray_ShouldReturnEmptyArray()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new SystemTextJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var emptyArrayJson = "[]";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(emptyArrayJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Should().BeEmpty();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithSystemTextJson_InvalidJson_ShouldThrowException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new SystemTextJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var invalidJson = "not valid json";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Action act = () => serializer.DeserializeJsonToArray<MappingModel>(invalidJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<Exception>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithSystemTextJson_ComplexMapping_ShouldDeserializeCorrectly()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new SystemTextJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var complexJson =
|
||||||
|
"""
|
||||||
|
{
|
||||||
|
"Guid": "12345678-1234-1234-1234-123456789012",
|
||||||
|
"Title": "Test Mapping",
|
||||||
|
"Description": "A test mapping",
|
||||||
|
"Priority": 10,
|
||||||
|
"Request": {
|
||||||
|
"Path": "/api/test",
|
||||||
|
"Methods": ["GET", "POST"]
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 201,
|
||||||
|
"Body": "Test Response"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
""";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = serializer.DeserializeJsonToArray<MappingModel>(complexJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().NotBeNull();
|
||||||
|
result.Should().HaveCount(1);
|
||||||
|
result[0].Guid.Should().Be(Guid.Parse("12345678-1234-1234-1234-123456789012"));
|
||||||
|
result[0].Title.Should().Be("Test Mapping");
|
||||||
|
result[0].Description.Should().Be("A test mapping");
|
||||||
|
result[0].Priority.Should().Be(10);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithSystemTextJson_NullValue_ShouldThrowException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new SystemTextJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var nullJson = "null";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Action act = () => serializer.DeserializeJsonToArray<MappingModel>(nullJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<Exception>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void MappingSerializer_DeserializeJsonToArray_WithSystemTextJson_PrimitiveValue_ShouldThrowInvalidOperationException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var jsonConverter = new SystemTextJsonConverter();
|
||||||
|
var serializer = new MappingSerializer(jsonConverter);
|
||||||
|
var primitiveJson = "\"string value\"";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Action act = () => serializer.DeserializeJsonToArray<MappingModel>(primitiveJson);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<InvalidOperationException>()
|
||||||
|
.WithMessage("Cannot deserialize the provided value to an array or object.");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
@@ -7,6 +7,8 @@ using System.Threading.Tasks;
|
|||||||
using DotNet.Testcontainers.Builders;
|
using DotNet.Testcontainers.Builders;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using FluentAssertions.Execution;
|
using FluentAssertions.Execution;
|
||||||
|
using Meziantou.Extensions.Logging.Xunit;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using WireMock.Net.Testcontainers;
|
using WireMock.Net.Testcontainers;
|
||||||
using WireMock.Net.Testcontainers.Utils;
|
using WireMock.Net.Testcontainers.Utils;
|
||||||
using WireMock.Net.Tests.Facts;
|
using WireMock.Net.Tests.Facts;
|
||||||
@@ -17,6 +19,12 @@ namespace WireMock.Net.Tests.Testcontainers;
|
|||||||
|
|
||||||
public class TestcontainersTests(ITestOutputHelper testOutputHelper)
|
public class TestcontainersTests(ITestOutputHelper testOutputHelper)
|
||||||
{
|
{
|
||||||
|
private readonly ILogger _logger = new XUnitLogger(testOutputHelper, new LoggerExternalScopeProvider(), nameof(TestcontainersTests), new XUnitLoggerOptions
|
||||||
|
{
|
||||||
|
IncludeCategory = true,
|
||||||
|
TimestampFormat = "yyy-MM-dd HH:mm:ss.fff"
|
||||||
|
});
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WireMockContainer_Build_And_StartAsync_and_StopAsync()
|
public async Task WireMockContainer_Build_And_StartAsync_and_StopAsync()
|
||||||
{
|
{
|
||||||
@@ -24,6 +32,7 @@ public class TestcontainersTests(ITestOutputHelper testOutputHelper)
|
|||||||
var adminUsername = $"username_{Guid.NewGuid()}";
|
var adminUsername = $"username_{Guid.NewGuid()}";
|
||||||
var adminPassword = $"password_{Guid.NewGuid()}";
|
var adminPassword = $"password_{Guid.NewGuid()}";
|
||||||
var wireMockContainer = new WireMockContainerBuilder()
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithLogger(_logger)
|
||||||
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
|
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
|
||||||
.WithAutoRemove(true)
|
.WithAutoRemove(true)
|
||||||
.WithCleanUp(true)
|
.WithCleanUp(true)
|
||||||
@@ -43,6 +52,7 @@ public class TestcontainersTests(ITestOutputHelper testOutputHelper)
|
|||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var wireMockContainer = new WireMockContainerBuilder()
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithLogger(_logger)
|
||||||
.WithNetwork(dummyNetwork)
|
.WithNetwork(dummyNetwork)
|
||||||
.WithWatchStaticMappings(true)
|
.WithWatchStaticMappings(true)
|
||||||
.Build();
|
.Build();
|
||||||
@@ -58,6 +68,7 @@ public class TestcontainersTests(ITestOutputHelper testOutputHelper)
|
|||||||
var adminUsername = $"username_{Guid.NewGuid()}";
|
var adminUsername = $"username_{Guid.NewGuid()}";
|
||||||
var adminPassword = $"password_{Guid.NewGuid()}";
|
var adminPassword = $"password_{Guid.NewGuid()}";
|
||||||
var wireMockContainerBuilder = new WireMockContainerBuilder()
|
var wireMockContainerBuilder = new WireMockContainerBuilder()
|
||||||
|
.WithLogger(_logger)
|
||||||
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
|
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
|
||||||
|
|
||||||
var imageOS = await TestcontainersUtils.GetImageOSAsync.Value;
|
var imageOS = await TestcontainersUtils.GetImageOSAsync.Value;
|
||||||
@@ -83,6 +94,7 @@ public class TestcontainersTests(ITestOutputHelper testOutputHelper)
|
|||||||
var adminUsername = $"username_{Guid.NewGuid()}";
|
var adminUsername = $"username_{Guid.NewGuid()}";
|
||||||
var adminPassword = $"password_{Guid.NewGuid()}";
|
var adminPassword = $"password_{Guid.NewGuid()}";
|
||||||
var wireMockContainerBuilder = new WireMockContainerBuilder()
|
var wireMockContainerBuilder = new WireMockContainerBuilder()
|
||||||
|
.WithLogger(_logger)
|
||||||
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
|
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
|
||||||
|
|
||||||
var imageOS = await TestcontainersUtils.GetImageOSAsync.Value;
|
var imageOS = await TestcontainersUtils.GetImageOSAsync.Value;
|
||||||
|
|||||||
@@ -11,6 +11,8 @@ using FluentAssertions;
|
|||||||
using FluentAssertions.Execution;
|
using FluentAssertions.Execution;
|
||||||
using Greet;
|
using Greet;
|
||||||
using Grpc.Net.Client;
|
using Grpc.Net.Client;
|
||||||
|
using Meziantou.Extensions.Logging.Xunit;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using WireMock.Constants;
|
using WireMock.Constants;
|
||||||
using WireMock.Net.Testcontainers;
|
using WireMock.Net.Testcontainers;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
@@ -22,7 +24,13 @@ namespace WireMock.Net.Tests.Testcontainers;
|
|||||||
[Collection("Grpc")]
|
[Collection("Grpc")]
|
||||||
public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
||||||
{
|
{
|
||||||
[Fact(Skip = "TODO")]
|
private readonly ILogger _logger = new XUnitLogger(testOutputHelper, new LoggerExternalScopeProvider(), nameof(TestcontainersTestsGrpc), new XUnitLoggerOptions
|
||||||
|
{
|
||||||
|
IncludeCategory = true,
|
||||||
|
TimestampFormat = "yyy-MM-dd HH:mm:ss.fff"
|
||||||
|
});
|
||||||
|
|
||||||
|
[Fact]
|
||||||
public async Task WireMockContainer_Build_Grpc_TestPortsAndUrls1()
|
public async Task WireMockContainer_Build_Grpc_TestPortsAndUrls1()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
@@ -32,6 +40,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
|||||||
|
|
||||||
// Act
|
// Act
|
||||||
var wireMockContainer = new WireMockContainerBuilder()
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithLogger(_logger)
|
||||||
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
|
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
|
||||||
.WithCommand("--UseHttp2")
|
.WithCommand("--UseHttp2")
|
||||||
.WithCommand("--Urls", $"http://*:80 grpc://*:{port}")
|
.WithCommand("--Urls", $"http://*:80 grpc://*:{port}")
|
||||||
@@ -78,7 +87,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "TODO")]
|
[Fact]
|
||||||
public async Task WireMockContainer_Build_Grpc_TestPortsAndUrls2()
|
public async Task WireMockContainer_Build_Grpc_TestPortsAndUrls2()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
@@ -88,6 +97,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
|||||||
|
|
||||||
// Act
|
// Act
|
||||||
var wireMockContainer = new WireMockContainerBuilder()
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithLogger(_logger)
|
||||||
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
|
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
|
||||||
.AddUrl($"http://*:{ports[0]}")
|
.AddUrl($"http://*:{ports[0]}")
|
||||||
.AddUrl($"grpc://*:{ports[1]}")
|
.AddUrl($"grpc://*:{ports[1]}")
|
||||||
@@ -131,7 +141,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "TODO")]
|
[Fact]
|
||||||
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionFromJson_UsingGrpcGeneratedClient()
|
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionFromJson_UsingGrpcGeneratedClient()
|
||||||
{
|
{
|
||||||
var wireMockContainer = await Given_WireMockContainerIsStartedForHttpAndGrpcAsync();
|
var wireMockContainer = await Given_WireMockContainerIsStartedForHttpAndGrpcAsync();
|
||||||
@@ -145,7 +155,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
|||||||
await StopAsync(wireMockContainer);
|
await StopAsync(wireMockContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "TODO")]
|
[Fact]
|
||||||
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient()
|
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient()
|
||||||
{
|
{
|
||||||
var wireMockContainer = await Given_WireMockContainerWithProtoDefinitionAtServerLevelIsStartedForHttpAndGrpcAsync();
|
var wireMockContainer = await Given_WireMockContainerWithProtoDefinitionAtServerLevelIsStartedForHttpAndGrpcAsync();
|
||||||
@@ -159,7 +169,7 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
|||||||
await StopAsync(wireMockContainer);
|
await StopAsync(wireMockContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(Skip = "TODO")]
|
[Fact]
|
||||||
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient_AndWithWatchStaticMappings()
|
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient_AndWithWatchStaticMappings()
|
||||||
{
|
{
|
||||||
var wireMockContainer = await Given_WireMockContainerWithProtoDefinitionAtServerLevelWithWatchStaticMappingsIsStartedForHttpAndGrpcAsync();
|
var wireMockContainer = await Given_WireMockContainerWithProtoDefinitionAtServerLevelWithWatchStaticMappingsIsStartedForHttpAndGrpcAsync();
|
||||||
@@ -222,10 +232,11 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<WireMockContainer> Given_WireMockContainerIsStartedForHttpAndGrpcAsync()
|
private async Task<WireMockContainer> Given_WireMockContainerIsStartedForHttpAndGrpcAsync()
|
||||||
{
|
{
|
||||||
var port = PortUtils.FindFreeTcpPort();
|
var port = PortUtils.FindFreeTcpPort();
|
||||||
var wireMockContainer = new WireMockContainerBuilder()
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithLogger(_logger)
|
||||||
.AddUrl($"grpc://*:{port}")
|
.AddUrl($"grpc://*:{port}")
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
@@ -234,10 +245,11 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
|||||||
return wireMockContainer;
|
return wireMockContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<WireMockContainer> Given_WireMockContainerWithProtoDefinitionAtServerLevelIsStartedForHttpAndGrpcAsync()
|
private async Task<WireMockContainer> Given_WireMockContainerWithProtoDefinitionAtServerLevelIsStartedForHttpAndGrpcAsync()
|
||||||
{
|
{
|
||||||
var port = PortUtils.FindFreeTcpPort();
|
var port = PortUtils.FindFreeTcpPort();
|
||||||
var wireMockContainer = new WireMockContainerBuilder()
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithLogger(_logger)
|
||||||
.AddUrl($"grpc://*:{port}")
|
.AddUrl($"grpc://*:{port}")
|
||||||
.AddProtoDefinition("my-greeter", ReadFile("greet.proto"))
|
.AddProtoDefinition("my-greeter", ReadFile("greet.proto"))
|
||||||
.Build();
|
.Build();
|
||||||
@@ -247,10 +259,11 @@ public class TestcontainersTestsGrpc(ITestOutputHelper testOutputHelper)
|
|||||||
return wireMockContainer;
|
return wireMockContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<WireMockContainer> Given_WireMockContainerWithProtoDefinitionAtServerLevelWithWatchStaticMappingsIsStartedForHttpAndGrpcAsync()
|
private async Task<WireMockContainer> Given_WireMockContainerWithProtoDefinitionAtServerLevelWithWatchStaticMappingsIsStartedForHttpAndGrpcAsync()
|
||||||
{
|
{
|
||||||
var port = PortUtils.FindFreeTcpPort();
|
var port = PortUtils.FindFreeTcpPort();
|
||||||
var wireMockContainer = new WireMockContainerBuilder()
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithLogger(_logger)
|
||||||
.AddUrl($"grpc://*:{port}")
|
.AddUrl($"grpc://*:{port}")
|
||||||
.AddProtoDefinition("my-greeter", ReadFile("greet.proto"))
|
.AddProtoDefinition("my-greeter", ReadFile("greet.proto"))
|
||||||
.WithMappings(Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings"))
|
.WithMappings(Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings"))
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<Authors>Stef Heyenrath</Authors>
|
||||||
@@ -107,7 +107,7 @@
|
|||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' != 'net452'">
|
<ItemGroup Condition="'$(TargetFramework)' != 'net452'">
|
||||||
<PackageReference Include="System.Net.Http.Json" Version="8.0.1" />
|
<PackageReference Include="System.Net.Http.Json" Version="8.0.1" />
|
||||||
<PackageReference Include="JsonConverter.System.Text.Json" Version="0.7.0" />
|
<!--<PackageReference Include="JsonConverter.System.Text.Json" Version="0.8.0" />-->
|
||||||
<PackageReference Include="Google.Protobuf" Version="3.25.1" />
|
<PackageReference Include="Google.Protobuf" Version="3.25.1" />
|
||||||
<PackageReference Include="Grpc.Net.Client" Version="2.60.0" />
|
<PackageReference Include="Grpc.Net.Client" Version="2.60.0" />
|
||||||
<PackageReference Include="Grpc.Tools" Version="2.60.0">
|
<PackageReference Include="Grpc.Tools" Version="2.60.0">
|
||||||
@@ -121,6 +121,7 @@
|
|||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj" />
|
||||||
|
<PackageReference Include="Meziantou.Extensions.Logging.Xunit" Version="1.0.21" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -6,7 +6,6 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Net.Http.Headers;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
@@ -34,11 +33,10 @@ public partial class WireMockServerTests
|
|||||||
Request.Create()
|
Request.Create()
|
||||||
.WithPath("/a")
|
.WithPath("/a")
|
||||||
.WithBody(
|
.WithBody(
|
||||||
new IMatcher[]
|
[
|
||||||
{
|
|
||||||
new JmesPathMatcher("requestId == '1'"),
|
new JmesPathMatcher("requestId == '1'"),
|
||||||
new JmesPathMatcher("value == 'A'")
|
new JmesPathMatcher("value == 'A'")
|
||||||
},
|
],
|
||||||
MatchOperator.And
|
MatchOperator.And
|
||||||
)
|
)
|
||||||
.UsingPost()
|
.UsingPost()
|
||||||
@@ -49,11 +47,10 @@ public partial class WireMockServerTests
|
|||||||
Request.Create()
|
Request.Create()
|
||||||
.WithPath("/a")
|
.WithPath("/a")
|
||||||
.WithBody(
|
.WithBody(
|
||||||
new IMatcher[]
|
[
|
||||||
{
|
|
||||||
new JmesPathMatcher("requestId == '2'"),
|
new JmesPathMatcher("requestId == '2'"),
|
||||||
new JmesPathMatcher("value == 'A'")
|
new JmesPathMatcher("value == 'A'")
|
||||||
},
|
],
|
||||||
MatchOperator.And
|
MatchOperator.And
|
||||||
)
|
)
|
||||||
.UsingPost()
|
.UsingPost()
|
||||||
@@ -81,12 +78,11 @@ public partial class WireMockServerTests
|
|||||||
Request.Create()
|
Request.Create()
|
||||||
.WithPath("/a")
|
.WithPath("/a")
|
||||||
.WithBody(
|
.WithBody(
|
||||||
new IMatcher[]
|
[
|
||||||
{
|
|
||||||
new JmesPathMatcher("extra == 'X'"),
|
new JmesPathMatcher("extra == 'X'"),
|
||||||
new JmesPathMatcher("requestId == '1'"),
|
new JmesPathMatcher("requestId == '1'"),
|
||||||
new JmesPathMatcher("value == 'A'")
|
new JmesPathMatcher("value == 'A'")
|
||||||
},
|
],
|
||||||
MatchOperator.And
|
MatchOperator.And
|
||||||
)
|
)
|
||||||
.UsingPost()
|
.UsingPost()
|
||||||
@@ -98,11 +94,10 @@ public partial class WireMockServerTests
|
|||||||
Request.Create()
|
Request.Create()
|
||||||
.WithPath("/a")
|
.WithPath("/a")
|
||||||
.WithBody(
|
.WithBody(
|
||||||
new IMatcher[]
|
[
|
||||||
{
|
|
||||||
new JmesPathMatcher("requestId == '1'"),
|
new JmesPathMatcher("requestId == '1'"),
|
||||||
new JmesPathMatcher("value == 'A'")
|
new JmesPathMatcher("value == 'A'")
|
||||||
},
|
],
|
||||||
MatchOperator.And
|
MatchOperator.And
|
||||||
)
|
)
|
||||||
.UsingPost()
|
.UsingPost()
|
||||||
@@ -188,6 +183,7 @@ public partial class WireMockServerTests
|
|||||||
{"jsonrpc":"2.0","id":"{{request.bodyAsJson.id}}","result":{"protocolVersion":"2024-11-05","capabilities":{"logging":{},"prompts":{"listChanged":true},"resources":{"subscribe":true,"listChanged":true},"tools":{"listChanged":true}},"serverInfo":{"name":"ExampleServer","version":"1.0.0"}}}
|
{"jsonrpc":"2.0","id":"{{request.bodyAsJson.id}}","result":{"protocolVersion":"2024-11-05","capabilities":{"logging":{},"prompts":{"listChanged":true},"resources":{"subscribe":true,"listChanged":true},"tools":{"listChanged":true}},"serverInfo":{"name":"ExampleServer","version":"1.0.0"}}}
|
||||||
""")
|
""")
|
||||||
.WithStatusCode(200)
|
.WithStatusCode(200)
|
||||||
|
.WithTransformer(true)
|
||||||
);
|
);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
@@ -199,15 +195,47 @@ public partial class WireMockServerTests
|
|||||||
// Assert
|
// Assert
|
||||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
|
||||||
var responseText = await response.RequestMessage!.Content!.ReadAsStringAsync();
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
responseText.Should().Contain("ec475f56d4694b48bc737500ba575b35-1");
|
responseText.Should().Contain("ec475f56d4694b48bc737500ba575b35-1");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
[Fact]
|
||||||
|
public async Task WireMockServer_WithBodyAsJson_Using_PostAsync_And_JsonPartialWildcardMatcher_And_SystemTextJson_ShouldMatch()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var server = WireMockServer.Start(x => x.DefaultJsonSerializer = new JsonConverter.System.Text.Json.SystemTextJsonConverter() );
|
||||||
|
|
||||||
|
var matcher = new JsonPartialWildcardMatcher(new { id = "^[a-f0-9]{32}-[0-9]$" }, ignoreCase: true, regex: true);
|
||||||
|
server.Given(Request.Create()
|
||||||
|
.WithHeader("Content-Type", "application/json*")
|
||||||
|
.UsingPost()
|
||||||
|
.WithPath("/system-text-json")
|
||||||
|
.WithBody(matcher)
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithBody("OK")
|
||||||
|
);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var content = """{"id":"ec475f56d4694b48bc737500ba575b35-1"}""";
|
||||||
|
var response = await new HttpClient()
|
||||||
|
.PostAsync($"{server.Url}/system-text-json", new StringContent(content, Encoding.UTF8, "application/json"))
|
||||||
|
.ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||||
|
|
||||||
|
var responseText = await response.Content.ReadAsStringAsync();
|
||||||
|
responseText.Should().Contain("OK");
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithFunc()
|
public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithFunc()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var server = WireMockServer.Start();
|
using var server = WireMockServer.Start();
|
||||||
server.Given(
|
server.Given(
|
||||||
Request.Create()
|
Request.Create()
|
||||||
.UsingPost()
|
.UsingPost()
|
||||||
@@ -219,7 +247,7 @@ public partial class WireMockServerTests
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var content = new FormUrlEncodedContent(new[] { new KeyValuePair<string, string>("key1", "value1") });
|
var content = new FormUrlEncodedContent([new KeyValuePair<string, string>("key1", "value1")]);
|
||||||
var response = await new HttpClient()
|
var response = await new HttpClient()
|
||||||
.PostAsync($"{server.Url}/foo", content)
|
.PostAsync($"{server.Url}/foo", content)
|
||||||
.ConfigureAwait(false);
|
.ConfigureAwait(false);
|
||||||
|
|||||||
Reference in New Issue
Block a user