mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-07-18 02:31:26 +02:00
Compare commits
17 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| ad86db7bb7 | |||
| b7406f1587 | |||
| d270ad7f4f | |||
| 345efe8cfc | |||
| a74468e780 | |||
| 041160d824 | |||
| 0933a120bc | |||
| 1ab6ca5531 | |||
| 4666757df9 | |||
| 49dcbda647 | |||
| cbc28c235c | |||
| dd1aa5139e | |||
| 89b3149732 | |||
| d2b794ec5a | |||
| 921a3ebc63 | |||
| 428657a97e | |||
| fe9745235a |
@@ -1,3 +1,31 @@
|
||||
# 2.12.0 (07 July 2026)
|
||||
- [#1479](https://github.com/wiremock/WireMock.Net/pull/1479) - Upgrade Microsoft.OpenApi to 3.7.0 and YamlDotNet to 18.1.0 [security] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1480](https://github.com/wiremock/WireMock.Net/pull/1480) - Upgrade RamlToOpenApiConverter.SourceOnly to 0.21.0 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1484](https://github.com/wiremock/WireMock.Net/pull/1484) - Update Scriban.Signed package version to 7.2.5 [security] contributed by [johnthcall](https://github.com/johnthcall)
|
||||
- [#1487](https://github.com/wiremock/WireMock.Net/pull/1487) - Response.Create() sets the DateTime to UtcNow [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1486](https://github.com/wiremock/WireMock.Net/issues/1486) - ResponseMessage.DateTime defaults to DateTime.MinValue, causing premature log entry purging for *matched* requests [bug]
|
||||
|
||||
# 2.11.0 (12 June 2026)
|
||||
- [#1475](https://github.com/wiremock/WireMock.Net/pull/1475) - Update NuGet packages (Aspire, MessagePack and more) [security] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1476](https://github.com/wiremock/WireMock.Net/pull/1476) - Fix BodyParser [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1473](https://github.com/wiremock/WireMock.Net/issues/1473) - JsonPartialWildCardMatcher With DateTime Regex Stopped Matching (Regression?) [bug]
|
||||
|
||||
# 2.10.0 (07 June 2026)
|
||||
- [#1472](https://github.com/wiremock/WireMock.Net/pull/1472) - Update JsonConverter to 0.13.0 [bug] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 2.9.0 (02 June 2026)
|
||||
- [#1470](https://github.com/wiremock/WireMock.Net/pull/1470) - Fix WireMock.Net.Aspire project when using Aspire 13.4.0 [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1469](https://github.com/wiremock/WireMock.Net/issues/1469) - WireMock.Net doesn't play well with Aspire 13.4.0 [bug]
|
||||
|
||||
# 2.8.0 (31 May 2026)
|
||||
- [#1447](https://github.com/wiremock/WireMock.Net/pull/1447) - Add SystemTextJsonMatchers [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1466](https://github.com/wiremock/WireMock.Net/pull/1466) - Bump System.Text.RegularExpressions from 4.3.0 to 4.3.1 in Aspire Example project [dependencies, .NET] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#1467](https://github.com/wiremock/WireMock.Net/pull/1467) - Bump System.Net.Http from 4.3.0 to 4.3.4 in Aspire Example project [dependencies, .NET] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#1468](https://github.com/wiremock/WireMock.Net/pull/1468) - Update JsonMatcher to support IgnoreArrayOrder [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1439](https://github.com/wiremock/WireMock.Net/issues/1439) - JSON reference properties cannot be used when using System.Text.Json serialization [bug]
|
||||
- [#1445](https://github.com/wiremock/WireMock.Net/issues/1445) - Configurable JSON DE-serialization support (Newtonsoft.Json vs System.Text.Json) [feature]
|
||||
- [#1460](https://github.com/wiremock/WireMock.Net/issues/1460) - Option to ignore array order when comparing json body [feature]
|
||||
|
||||
# 2.7.0 (24 May 2026)
|
||||
- [#1457](https://github.com/wiremock/WireMock.Net/pull/1457) - Update OpenTelemetry.Api from 1.14.0 to 1.15.3 in unit test project [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#1459](https://github.com/wiremock/WireMock.Net/pull/1459) - chore: update Handlebars 2.5.2 to 2.5.5 [dependencies] contributed by [kamisoft-fr](https://github.com/kamisoft-fr)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>2.8.0</VersionPrefix>
|
||||
<VersionPrefix>2.12.0</VersionPrefix>
|
||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
@@ -52,7 +52,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2025.2.4" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.103" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.300" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
rem https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
SET version=2.8.0
|
||||
SET version=2.12.0
|
||||
|
||||
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,8 @@
|
||||
# 2.7.0 (24 May 2026)
|
||||
- #1457 Update OpenTelemetry.Api from 1.14.0 to 1.15.3 in unit test project [dependencies]
|
||||
- #1459 chore: update Handlebars 2.5.2 to 2.5.5 [dependencies]
|
||||
- #1461 Update Testcontainers nuget package to 4.12.0 [dependencies]
|
||||
- #1462 Update Scriban.Signed to latest [dependencies]
|
||||
- #1458 update Handlebars Humanizer package version [feature]
|
||||
# 2.12.0 (07 July 2026)
|
||||
- #1479 Upgrade Microsoft.OpenApi to 3.7.0 and YamlDotNet to 18.1.0 [security]
|
||||
- #1480 Upgrade RamlToOpenApiConverter.SourceOnly to 0.21.0 [feature]
|
||||
- #1484 Update Scriban.Signed package version to 7.2.5 [security]
|
||||
- #1487 Response.Create() sets the DateTime to UtcNow [bug]
|
||||
- #1486 ResponseMessage.DateTime defaults to DateTime.MinValue, causing premature log entry purging for *matched* requests [bug]
|
||||
|
||||
The full release notes can be found here: https://github.com/wiremock/WireMock.Net/blob/master/CHANGELOG.md
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="13.1.0" />
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="13.4.0" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -18,7 +18,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.1.0" />
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.4.3" />
|
||||
|
||||
<!-- CVE-2026-48109 -->
|
||||
<PackageReference Include="MessagePack" Version="2.5.302" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="13.1.0" />
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="13.4.0" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -15,7 +15,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.1.0" />
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.4.3" />
|
||||
|
||||
<!-- CVE-2026-48109 -->
|
||||
<PackageReference Include="MessagePack" Version="2.5.302" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -9,9 +9,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Google.Protobuf" Version="3.25.1" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.60.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.60.0">
|
||||
<PackageReference Include="Google.Protobuf" Version="3.33.5" />
|
||||
<PackageReference Include="Grpc.Net.Client" Version="2.76.0" />
|
||||
<PackageReference Include="Grpc.Tools" Version="2.78.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="WireMock.Net" Version="2.6.0" />
|
||||
<PackageReference Include="WireMock.Net" Version="2.10.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
+2
-5
@@ -6,7 +6,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="3.7.0" />
|
||||
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.OpenApiParser\WireMock.Net.OpenApiParser.csproj" />
|
||||
@@ -14,10 +14,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="2.3.0" PrivateAssets="All" />
|
||||
<!--<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="2.3.0" PrivateAssets="All" />
|
||||
<PackageReference Include="System.Text.Json" Version="8.0.5" />
|
||||
<PackageReference Include="SharpYaml" Version="2.1.3" />-->
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="3.7.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
<Version>2.3.9</Version>
|
||||
</PackageReference>
|
||||
<PackageReference Include="WireMock.Net">
|
||||
<Version>1.25.0</Version>
|
||||
<Version>2.10.0</Version>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
</ItemGroup>-->
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="FluentBuilder" Version="0.14.0">
|
||||
<PackageReference Include="FluentBuilder" Version="0.15.0">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -45,7 +45,10 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting" Version="13.1.0" />
|
||||
<PackageReference Include="Aspire.Hosting" Version="13.4.3" />
|
||||
|
||||
<!-- CVE-2026-48109 -->
|
||||
<PackageReference Include="MessagePack" Version="2.5.302" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -21,11 +21,6 @@ public class WireMockHealthCheck(WireMockServerResource resource) : IHealthCheck
|
||||
return HealthCheckResult.Unhealthy("WireMock.Net is not healthy");
|
||||
}
|
||||
|
||||
if (resource.ApiMappingState == WireMockMappingState.NotSubmitted)
|
||||
{
|
||||
return HealthCheckResult.Unhealthy("WireMock.Net has not received mappings");
|
||||
}
|
||||
|
||||
return HealthCheckResult.Healthy();
|
||||
}
|
||||
|
||||
@@ -41,4 +36,4 @@ public class WireMockHealthCheck(WireMockServerResource resource) : IHealthCheck
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,7 +21,13 @@ internal class WireMockLifecycleSubscriber(ILoggerFactory loggerFactory) : IDist
|
||||
|
||||
var endpoint = wireMockServerResource.GetEndpoint();
|
||||
Debug.Assert(endpoint.IsAllocated);
|
||||
}
|
||||
});
|
||||
|
||||
eventing.Subscribe<ResourceReadyEvent>(async (@event, ct) =>
|
||||
{
|
||||
if (@event.Resource is WireMockServerResource wireMockServerResource)
|
||||
{
|
||||
await wireMockServerResource.WaitForHealthAsync(ct);
|
||||
|
||||
await wireMockServerResource.CallAddProtoDefinitionsAsync(ct);
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JsonConverter.Abstractions" Version="0.12.0" />
|
||||
<PackageReference Include="JsonConverter.Abstractions" Version="0.13.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
|
||||
@@ -66,6 +66,7 @@ internal partial class AspNetCoreSelfHost
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton(_wireMockMiddlewareOptions);
|
||||
services.AddSingleton(_wireMockMiddlewareOptions.AdminPaths);
|
||||
services.AddSingleton<IMappingMatcher, MappingMatcher>();
|
||||
services.AddSingleton<IRandomizerDoubleBetween0And1, RandomizerDoubleBetween0And1>();
|
||||
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
using WireMock.Matchers;
|
||||
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal interface IAdminPaths
|
||||
{
|
||||
string Files { get; }
|
||||
string Health { get; }
|
||||
string Mappings { get; }
|
||||
string MappingsCode { get; }
|
||||
string MappingsWireMockOrg { get; }
|
||||
RegexMatcher MappingsGuidPathMatcher { get; }
|
||||
RegexMatcher MappingsGuidEnablePathMatcher { get; }
|
||||
RegexMatcher MappingsGuidDisablePathMatcher { get; }
|
||||
RegexMatcher MappingsCodeGuidPathMatcher { get; }
|
||||
RegexMatcher RequestsGuidPathMatcher { get; }
|
||||
RegexMatcher ScenariosNameMatcher { get; }
|
||||
RegexMatcher ScenariosNameWithStateMatcher { get; }
|
||||
RegexMatcher ScenariosNameWithResetMatcher { get; }
|
||||
RegexMatcher FilesFilenamePathMatcher { get; }
|
||||
RegexMatcher ProtoDefinitionsIdPathMatcher { get; }
|
||||
string Requests { get; }
|
||||
string Settings { get; }
|
||||
string Scenarios { get; }
|
||||
string OpenApi { get; }
|
||||
string ProtoDefinitions { get; }
|
||||
bool Includes(string? path);
|
||||
}
|
||||
@@ -108,4 +108,6 @@ internal interface IWireMockMiddlewareOptions
|
||||
/// Set this property to customize how objects are serialized to and deserialized from JSON during mapping.
|
||||
/// </remarks>
|
||||
IJsonConverter DefaultJsonSerializer { get; set; }
|
||||
|
||||
IAdminPaths AdminPaths { get; set; }
|
||||
}
|
||||
@@ -21,6 +21,7 @@ internal class WireMockMiddleware(
|
||||
RequestDelegate next,
|
||||
#pragma warning restore CS9113 // Parameter is unread.
|
||||
IWireMockMiddlewareOptions options,
|
||||
IAdminPaths adminPaths,
|
||||
IOwinRequestMapper requestMapper,
|
||||
IOwinResponseMapper responseMapper,
|
||||
IMappingMatcher mappingMatcher,
|
||||
@@ -64,7 +65,7 @@ internal class WireMockMiddleware(
|
||||
Activity? activity = null;
|
||||
|
||||
// Check if we should trace this request (optionally exclude admin requests)
|
||||
var shouldTrace = tracingEnabled && !(excludeAdmin && request.Path.StartsWith("/__admin/"));
|
||||
var shouldTrace = tracingEnabled && !(excludeAdmin && adminPaths.Includes(request.Path));
|
||||
|
||||
if (shouldTrace)
|
||||
{
|
||||
|
||||
@@ -9,39 +9,44 @@ using WireMock.Util;
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal class WireMockMiddlewareLogger(
|
||||
IWireMockMiddlewareOptions _options,
|
||||
LogEntryMapper _logEntryMapper,
|
||||
IGuidUtils _guidUtils
|
||||
IWireMockMiddlewareOptions options,
|
||||
LogEntryMapper logEntryMapper,
|
||||
IGuidUtils guidUtils,
|
||||
IAdminPaths adminPaths,
|
||||
IDateTimeUtils dateTimeUtils
|
||||
) : IWireMockMiddlewareLogger
|
||||
{
|
||||
public void LogRequestAndResponse(bool logRequest, RequestMessage request, IResponseMessage? response, MappingMatcherResult? match, MappingMatcherResult? partialMatch, Activity? activity)
|
||||
{
|
||||
var mapping = match?.Mapping;
|
||||
var partialMapping = partialMatch?.Mapping;
|
||||
|
||||
var logEntry = new LogEntry
|
||||
{
|
||||
Guid = _guidUtils.NewGuid(),
|
||||
Guid = guidUtils.NewGuid(),
|
||||
RequestMessage = request,
|
||||
ResponseMessage = response,
|
||||
|
||||
MappingGuid = match?.Mapping?.Guid,
|
||||
MappingTitle = match?.Mapping?.Title,
|
||||
MappingGuid = mapping?.Guid,
|
||||
MappingTitle = mapping?.Title,
|
||||
RequestMatchResult = match?.RequestMatchResult,
|
||||
|
||||
PartialMappingGuid = partialMatch?.Mapping?.Guid,
|
||||
PartialMappingTitle = partialMatch?.Mapping?.Title,
|
||||
PartialMappingGuid = partialMapping?.Guid,
|
||||
PartialMappingTitle = partialMapping?.Title,
|
||||
PartialMatchResult = partialMatch?.RequestMatchResult
|
||||
};
|
||||
|
||||
WireMockActivitySource.EnrichWithLogEntry(activity, logEntry, _options.ActivityTracingOptions);
|
||||
WireMockActivitySource.EnrichWithLogEntry(activity, logEntry, options.ActivityTracingOptions);
|
||||
activity?.Dispose();
|
||||
|
||||
LogLogEntry(logEntry, logRequest);
|
||||
|
||||
try
|
||||
{
|
||||
if (_options.SaveUnmatchedRequests == true && match?.RequestMatchResult is not { IsPerfectMatch: true })
|
||||
if (options.SaveUnmatchedRequests == true && match?.RequestMatchResult is not { IsPerfectMatch: true })
|
||||
{
|
||||
var filename = $"{logEntry.Guid}.LogEntry.json";
|
||||
_options.FileSystemHandler?.WriteUnmatchedRequest(filename, _options.DefaultJsonSerializer.Serialize(logEntry));
|
||||
options.FileSystemHandler?.WriteUnmatchedRequest(filename, options.DefaultJsonSerializer.Serialize(logEntry));
|
||||
}
|
||||
}
|
||||
catch
|
||||
@@ -52,34 +57,35 @@ internal class WireMockMiddlewareLogger(
|
||||
|
||||
public void LogLogEntry(LogEntry entry, bool addRequest)
|
||||
{
|
||||
_options.Logger.DebugRequestResponse(_logEntryMapper.Map(entry), entry.RequestMessage?.Path.StartsWith("/__admin/") == true);
|
||||
var isAdminRequest = adminPaths.Includes(entry.RequestMessage?.Path);
|
||||
options.Logger.DebugRequestResponse(logEntryMapper.Map(entry), isAdminRequest);
|
||||
|
||||
// If addRequest is set to true and MaxRequestLogCount is null or does have a value greater than 0, try to add a new request log.
|
||||
if (addRequest && _options.MaxRequestLogCount is null or > 0)
|
||||
if (addRequest && options.MaxRequestLogCount is null or > 0)
|
||||
{
|
||||
TryAddLogEntry(entry);
|
||||
}
|
||||
|
||||
|
||||
// In case MaxRequestLogCount has a value greater than 0, try to delete existing request logs based on the count.
|
||||
if (_options.MaxRequestLogCount is > 0)
|
||||
if (options.MaxRequestLogCount is > 0)
|
||||
{
|
||||
var logEntries = _options.LogEntries.ToList();
|
||||
var logEntries = options.LogEntries.ToList();
|
||||
|
||||
foreach (var logEntry in logEntries
|
||||
.OrderBy(le => le.RequestMessage?.DateTime ?? le.ResponseMessage?.DateTime)
|
||||
.Take(logEntries.Count - _options.MaxRequestLogCount.Value))
|
||||
.Take(logEntries.Count - options.MaxRequestLogCount.Value))
|
||||
{
|
||||
TryRemoveLogEntry(logEntry);
|
||||
}
|
||||
}
|
||||
|
||||
// In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the date.
|
||||
if (_options.RequestLogExpirationDuration is > 0)
|
||||
if (options.RequestLogExpirationDuration is > 0)
|
||||
{
|
||||
var logEntries = _options.LogEntries.ToList();
|
||||
var logEntries = options.LogEntries.ToList();
|
||||
|
||||
var checkTime = DateTime.UtcNow.AddHours(-_options.RequestLogExpirationDuration.Value);
|
||||
var checkTime = dateTimeUtils.UtcNow.AddHours(-options.RequestLogExpirationDuration.Value);
|
||||
foreach (var logEntry in logEntries.Where(le => le.RequestMessage?.DateTime < checkTime || le.ResponseMessage?.DateTime < checkTime))
|
||||
{
|
||||
TryRemoveLogEntry(logEntry);
|
||||
@@ -91,7 +97,7 @@ internal class WireMockMiddlewareLogger(
|
||||
{
|
||||
try
|
||||
{
|
||||
_options.LogEntries.Add(logEntry);
|
||||
options.LogEntries.Add(logEntry);
|
||||
}
|
||||
catch
|
||||
{
|
||||
@@ -103,7 +109,7 @@ internal class WireMockMiddlewareLogger(
|
||||
{
|
||||
try
|
||||
{
|
||||
_options.LogEntries.Remove(logEntry);
|
||||
options.LogEntries.Remove(logEntry);
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
@@ -115,4 +115,7 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
||||
|
||||
/// <inheritdoc />
|
||||
public IJsonConverter DefaultJsonSerializer { get; set; } = new NewtonsoftJsonConverter();
|
||||
|
||||
/// <inheritdoc />
|
||||
public IAdminPaths AdminPaths { get; set; } = new AdminPaths(null);
|
||||
}
|
||||
@@ -34,6 +34,7 @@ internal static class WireMockMiddlewareOptionsHelper
|
||||
options.QueryParameterMultipleValueSupport = settings.QueryParameterMultipleValueSupport;
|
||||
options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
|
||||
options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
||||
options.AdminPaths = new AdminPaths(settings.AdminPath);
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
options.AdditionalServiceRegistration = settings.AdditionalServiceRegistration;
|
||||
|
||||
@@ -11,7 +11,6 @@ using WireMock.RequestBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Transformers;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
@@ -86,7 +85,11 @@ public partial class Response : IResponseBuilder
|
||||
[PublicAPI]
|
||||
public static IResponseBuilder Create(ResponseMessage? responseMessage = null)
|
||||
{
|
||||
var message = responseMessage ?? new ResponseMessage();
|
||||
var message = responseMessage ?? new ResponseMessage
|
||||
{
|
||||
DateTime = DateTime.UtcNow // We set it here to the current time.
|
||||
};
|
||||
|
||||
return new Response(message);
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Text.RegularExpressions;
|
||||
using WireMock.Matchers;
|
||||
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal sealed class AdminPaths(string? adminPath) : IAdminPaths
|
||||
{
|
||||
private const string DefaultAdminPathPrefix = "/__admin";
|
||||
|
||||
private readonly string _prefix = adminPath ?? DefaultAdminPathPrefix;
|
||||
|
||||
public string Files => $"{_prefix}/files";
|
||||
public string Health => $"{_prefix}/health";
|
||||
public string Mappings => $"{_prefix}/mappings";
|
||||
public string MappingsCode => $"{_prefix}/mappings/code";
|
||||
public string MappingsWireMockOrg => $"{_prefix}/mappings/wiremock.org";
|
||||
public string Requests => $"{_prefix}/requests";
|
||||
public string Settings => $"{_prefix}/settings";
|
||||
public string Scenarios => $"{_prefix}/scenarios";
|
||||
public string OpenApi => $"{_prefix}/openapi";
|
||||
public string ProtoDefinitions => $"{_prefix}/protodefinitions";
|
||||
|
||||
private string PrefixRegexEscaped => Regex.Escape(_prefix);
|
||||
public RegexMatcher MappingsGuidPathMatcher => new($@"^{PrefixRegexEscaped}\/mappings\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})$");
|
||||
public RegexMatcher MappingsGuidEnablePathMatcher => new($@"^{PrefixRegexEscaped}\/mappings\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})\/enable$");
|
||||
public RegexMatcher MappingsGuidDisablePathMatcher => new($@"^{PrefixRegexEscaped}\/mappings\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})\/disable$");
|
||||
public RegexMatcher MappingsCodeGuidPathMatcher => new($@"^{PrefixRegexEscaped}\/mappings\/code\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})$");
|
||||
public RegexMatcher RequestsGuidPathMatcher => new($@"^{PrefixRegexEscaped}\/requests\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})$");
|
||||
public RegexMatcher ScenariosNameMatcher => new($@"^{PrefixRegexEscaped}\/scenarios\/.+$");
|
||||
public RegexMatcher ScenariosNameWithStateMatcher => new($@"^{PrefixRegexEscaped}\/scenarios\/.+\/state$");
|
||||
public RegexMatcher ScenariosNameWithResetMatcher => new($@"^{PrefixRegexEscaped}\/scenarios\/.+\/reset$");
|
||||
public RegexMatcher FilesFilenamePathMatcher => new($@"^{PrefixRegexEscaped}\/files\/.+$");
|
||||
public RegexMatcher ProtoDefinitionsIdPathMatcher => new($@"^{PrefixRegexEscaped}\/protodefinitions\/.+$");
|
||||
|
||||
public bool Includes(string? path) => !string.IsNullOrEmpty(path) && path.StartsWith($"{_prefix}/");
|
||||
|
||||
public override string ToString() => _prefix;
|
||||
}
|
||||
@@ -19,7 +19,6 @@ using WireMock.Owin;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
@@ -28,50 +27,16 @@ namespace WireMock.Server;
|
||||
public partial class WireMockServer
|
||||
{
|
||||
private const int EnhancedFileSystemWatcherTimeoutMs = 1000;
|
||||
private const string DefaultAdminPathPrefix = "/__admin";
|
||||
private const string QueryParamReloadStaticMappings = "reloadStaticMappings";
|
||||
private static readonly Guid ProxyMappingGuid = new("e59914fd-782e-428e-91c1-4810ffb86567");
|
||||
private static readonly RegexMatcher AdminRequestContentTypeJson = new ContentTypeMatcher(WireMockConstants.ContentTypeJson, true);
|
||||
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
||||
private AdminPaths? _adminPaths;
|
||||
|
||||
private sealed class AdminPaths
|
||||
{
|
||||
private readonly string _prefix;
|
||||
private readonly string _prefixEscaped;
|
||||
|
||||
public AdminPaths(WireMockServerSettings settings)
|
||||
{
|
||||
_prefix = settings.AdminPath ?? DefaultAdminPathPrefix;
|
||||
_prefixEscaped = _prefix.Replace("/", "\\/");
|
||||
}
|
||||
|
||||
public string Files => $"{_prefix}/files";
|
||||
public string Health => $"{_prefix}/health";
|
||||
public string Mappings => $"{_prefix}/mappings";
|
||||
public string MappingsCode => $"{_prefix}/mappings/code";
|
||||
public string MappingsWireMockOrg => $"{_prefix}mappings/wiremock.org";
|
||||
public string Requests => $"{_prefix}/requests";
|
||||
public string Settings => $"{_prefix}/settings";
|
||||
public string Scenarios => $"{_prefix}/scenarios";
|
||||
public string OpenApi => $"{_prefix}/openapi";
|
||||
|
||||
public RegexMatcher MappingsGuidPathMatcher => new($"^{_prefixEscaped}\\/mappings\\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})$");
|
||||
public RegexMatcher MappingsGuidEnablePathMatcher => new($"^{_prefixEscaped}\\/mappings\\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})\\/enable$");
|
||||
public RegexMatcher MappingsGuidDisablePathMatcher => new($"^{_prefixEscaped}\\/mappings\\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})\\/disable$");
|
||||
public RegexMatcher MappingsCodeGuidPathMatcher => new($"^{_prefixEscaped}\\/mappings\\/code\\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})$");
|
||||
public RegexMatcher RequestsGuidPathMatcher => new($"^{_prefixEscaped}\\/requests\\/([0-9A-Fa-f]{{8}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{4}}[-][0-9A-Fa-f]{{12}})$");
|
||||
public RegexMatcher ScenariosNameMatcher => new($"^{_prefixEscaped}\\/scenarios\\/.+$");
|
||||
public RegexMatcher ScenariosNameWithStateMatcher => new($"^{_prefixEscaped}\\/scenarios\\/.+\\/state$");
|
||||
public RegexMatcher ScenariosNameWithResetMatcher => new($"^{_prefixEscaped}\\/scenarios\\/.+\\/reset$");
|
||||
public RegexMatcher FilesFilenamePathMatcher => new($"^{_prefixEscaped}\\/files\\/.+$");
|
||||
public RegexMatcher ProtoDefinitionsIdPathMatcher => new($"^{_prefixEscaped}\\/protodefinitions\\/.+$");
|
||||
}
|
||||
private IAdminPaths? _adminPaths;
|
||||
|
||||
#region InitAdmin
|
||||
private void InitAdmin()
|
||||
{
|
||||
_adminPaths = new AdminPaths(_settings);
|
||||
_adminPaths = _options.AdminPaths;
|
||||
|
||||
// __admin/health
|
||||
Given(Request.Create().WithPath(_adminPaths.Health).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(HealthGet));
|
||||
@@ -631,7 +596,7 @@ public partial class WireMockServer
|
||||
{
|
||||
if (TryParseGuidFromRequestMessage(requestMessage, out var guid))
|
||||
{
|
||||
var entry = LogEntries.SingleOrDefault(r => r.RequestMessage != null && !r.RequestMessage.Path.StartsWith("/__admin/") && r.Guid == guid);
|
||||
var entry = LogEntries.SingleOrDefault(r => r.RequestMessage != null && !_adminPaths!.Includes(r.RequestMessage.Path) && r.Guid == guid);
|
||||
if (entry is { })
|
||||
{
|
||||
var model = new LogEntryMapper(_options).Map(entry);
|
||||
@@ -660,7 +625,7 @@ public partial class WireMockServer
|
||||
{
|
||||
var logEntryMapper = new LogEntryMapper(_options);
|
||||
var result = LogEntries
|
||||
.Where(r => r.RequestMessage != null && !r.RequestMessage.Path.StartsWith("/__admin/"))
|
||||
.Where(r => r.RequestMessage != null && !_adminPaths!.Includes(r.RequestMessage.Path))
|
||||
.Select(logEntryMapper.Map);
|
||||
|
||||
return ToJson(result);
|
||||
@@ -682,7 +647,7 @@ public partial class WireMockServer
|
||||
var request = (Request)InitRequestBuilder(requestModel);
|
||||
|
||||
var dict = new Dictionary<ILogEntry, RequestMatchResult>();
|
||||
foreach (var logEntry in LogEntries.Where(le => le.RequestMessage != null && !le.RequestMessage.Path.StartsWith("/__admin/")))
|
||||
foreach (var logEntry in LogEntries.Where(le => le.RequestMessage != null && !_adminPaths!.Includes(le.RequestMessage.Path)))
|
||||
{
|
||||
var requestMatchResult = new RequestMatchResult();
|
||||
if (request.GetMatchingScore(logEntry.RequestMessage!, requestMatchResult) > MatchScores.AlmostPerfect)
|
||||
@@ -704,7 +669,7 @@ public partial class WireMockServer
|
||||
Guid.TryParse(value.ToString(), out var mappingGuid)
|
||||
)
|
||||
{
|
||||
var logEntries = LogEntries.Where(le => le.RequestMessage != null && !le.RequestMessage.Path.StartsWith("/__admin/") && le.MappingGuid == mappingGuid);
|
||||
var logEntries = LogEntries.Where(le => le.RequestMessage != null && !_adminPaths!.Includes(le.RequestMessage.Path) && le.MappingGuid == mappingGuid);
|
||||
var logEntryMapper = new LogEntryMapper(_options);
|
||||
var result = logEntries.Select(logEntryMapper.Map);
|
||||
return ToJson(result);
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||
<PackageReference Include="TinyMapper.Signed" Version="4.0.0" />
|
||||
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.34.0" />
|
||||
<PackageReference Include="Scriban.Signed" Version="7.2.0" />
|
||||
<PackageReference Include="Scriban.Signed" Version="7.2.5" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -85,4 +85,4 @@
|
||||
<ProjectReference Include="..\WireMock.Net.OpenApiParser\WireMock.Net.OpenApiParser.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -25,9 +25,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.12.0" />
|
||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.13.0" />
|
||||
<PackageReference Include="NUnit" Version="4.4.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -159,7 +159,7 @@ internal class OpenApiPathsMapper(WireMockOpenApiParserSettings settings)
|
||||
};
|
||||
}
|
||||
|
||||
private static bool TryGetContent(IDictionary<string, OpenApiMediaType>? contents, [NotNullWhen(true)] out OpenApiMediaType? openApiMediaType, [NotNullWhen(true)] out string? contentType)
|
||||
private static bool TryGetContent(IDictionary<string, IOpenApiMediaType>? contents, [NotNullWhen(true)] out IOpenApiMediaType? openApiMediaType, [NotNullWhen(true)] out string? contentType)
|
||||
{
|
||||
openApiMediaType = null;
|
||||
contentType = null;
|
||||
|
||||
@@ -40,21 +40,21 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="RamlToOpenApiConverter.SourceOnly" Version="0.11.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="16.3.0" />
|
||||
<PackageReference Include="RamlToOpenApiConverter.SourceOnly" Version="0.21.0" />
|
||||
<PackageReference Include="YamlDotNet" Version="18.1.0" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.19.1" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
|
||||
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="2.3.0" />
|
||||
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="3.7.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
||||
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.43" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="2.3.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="2.3.0" PrivateAssets="All" />
|
||||
<PackageReference Include="SharpYaml" Version="2.1.3" />
|
||||
<PackageReference Include="Microsoft.OpenApi" Version="3.7.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="3.7.0" PrivateAssets="All" />
|
||||
<PackageReference Include="SharpYaml" Version="2.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -65,6 +65,7 @@ public static class WireMockAdminApiExtensions
|
||||
waitTime = (int)(InitialWaitingTimeInMilliSeconds * Math.Pow(2, retries));
|
||||
await Task.Delay(waitTime, cancellationToken);
|
||||
isHealthy = await IsHealthyAsync(adminApi, cancellationToken);
|
||||
|
||||
retries++;
|
||||
totalWaitTime += waitTime;
|
||||
}
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.12.0" />
|
||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.13.0" />
|
||||
<PackageReference Include="RestEase" Version="1.6.4" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -305,12 +305,6 @@ public class WireMockServerSettings
|
||||
[PublicAPI, JsonIgnore]
|
||||
public IDictionary<string, Func<MatcherModel, IMatcher>>? CustomMatcherMappings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The <see cref="JsonSerializerSettings"/> used when the JSON response is generated.
|
||||
/// </summary>
|
||||
[PublicAPI, JsonIgnore]
|
||||
public JsonSerializerSettings? JsonSerializerSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Culture to use.
|
||||
/// Currently used for:
|
||||
|
||||
@@ -5,6 +5,7 @@ using System.Text;
|
||||
using Stef.Validation;
|
||||
using WireMock.Constants;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Util;
|
||||
@@ -25,7 +26,7 @@ internal static class BodyParser
|
||||
CONNECT - No defined body semantics
|
||||
PATCH - Body supported.
|
||||
*/
|
||||
private static readonly IDictionary<string, bool> BodyAllowedForMethods = new Dictionary<string, bool>
|
||||
private static readonly Dictionary<string, bool> BodyAllowedForMethods = new()
|
||||
{
|
||||
{ HttpRequestMethod.HEAD, false },
|
||||
{ HttpRequestMethod.GET, false },
|
||||
@@ -173,7 +174,7 @@ internal static class BodyParser
|
||||
{
|
||||
try
|
||||
{
|
||||
data.BodyAsJson = settings.DefaultJsonConverter.Deserialize<object>(data.BodyAsString);
|
||||
data.BodyAsJson = settings.DefaultJsonConverter.Deserialize<object>(data.BodyAsString, JsonSerializationConstants.JsonConverterOptionsWithDateParsingNone);
|
||||
data.DetectedBodyType = BodyType.Json;
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -27,11 +27,11 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.AspNetCore.Http" Version="2.3.9" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||
<PackageReference Include="AnyOf" Version="0.5.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.12.0" />
|
||||
<PackageReference Include="JsonConverter.System.Text.Json" Version="0.12.0" />
|
||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.13.0" />
|
||||
<PackageReference Include="JsonConverter.System.Text.Json" Version="0.13.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -27,7 +27,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||
<PackageReference Include="TUnit.Core" Version="1.17.29" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||
<PackageReference Include="Testcontainers" Version="4.12.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||
<PackageReference Include="xunit.v3.extensibility.core" Version="3.2.2" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Stef.Validation;
|
||||
using WireMock.Admin.Requests;
|
||||
@@ -14,51 +13,61 @@ namespace WireMock.Net.Xunit;
|
||||
/// </summary>
|
||||
public sealed class TestOutputHelperWireMockLogger : IWireMockLogger
|
||||
{
|
||||
private readonly ITestOutputHelper _testOutputHelper;
|
||||
private readonly Func<ITestOutputHelper?> _testOutputHelperFactory;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance on the <see cref="TestOutputHelperWireMockLogger"/>.
|
||||
/// </summary>
|
||||
/// <param name="testOutputHelper">Represents a class which can be used to provide test output.</param>
|
||||
public TestOutputHelperWireMockLogger(ITestOutputHelper testOutputHelper)
|
||||
public TestOutputHelperWireMockLogger(ITestOutputHelper testOutputHelper) :
|
||||
this(() => testOutputHelper)
|
||||
{
|
||||
_testOutputHelper = Guard.NotNull(testOutputHelper);
|
||||
Guard.NotNull(testOutputHelper);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance on the <see cref="TestOutputHelperWireMockLogger"/>.
|
||||
/// </summary>
|
||||
/// <param name="testOutputHelperFactory">Represents a factory to provide current test output.</param>
|
||||
public TestOutputHelperWireMockLogger(Func<ITestOutputHelper?> testOutputHelperFactory)
|
||||
{
|
||||
_testOutputHelperFactory = Guard.NotNull(testOutputHelperFactory);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Debug(string formatString, params object[] args)
|
||||
{
|
||||
_testOutputHelper.WriteLine(Format("Debug", formatString, args));
|
||||
_testOutputHelperFactory()?.WriteLine(Format("Debug", formatString, args));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Info(string formatString, params object[] args)
|
||||
{
|
||||
_testOutputHelper.WriteLine(Format("Info", formatString, args));
|
||||
_testOutputHelperFactory()?.WriteLine(Format("Info", formatString, args));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Warn(string formatString, params object[] args)
|
||||
{
|
||||
_testOutputHelper.WriteLine(Format("Warning", formatString, args));
|
||||
_testOutputHelperFactory()?.WriteLine(Format("Warning", formatString, args));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Error(string formatString, params object[] args)
|
||||
{
|
||||
_testOutputHelper.WriteLine(Format("Error", formatString, args));
|
||||
_testOutputHelperFactory()?.WriteLine(Format("Error", formatString, args));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Error(string message, Exception exception)
|
||||
{
|
||||
_testOutputHelper.WriteLine(Format("Error", $"{message} {{0}}", exception));
|
||||
_testOutputHelperFactory()?.WriteLine(Format("Error", $"{message} {{0}}", exception));
|
||||
|
||||
if (exception is AggregateException ae)
|
||||
{
|
||||
ae.Handle(ex =>
|
||||
{
|
||||
_testOutputHelper.WriteLine(Format("Error", "Exception {0}", ex));
|
||||
_testOutputHelperFactory()?.WriteLine(Format("Error", "Exception {0}", ex));
|
||||
return true;
|
||||
});
|
||||
}
|
||||
@@ -72,7 +81,7 @@ public sealed class TestOutputHelperWireMockLogger : IWireMockLogger
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
});
|
||||
_testOutputHelper.WriteLine(Format("DebugRequestResponse", "Admin[{0}] {1}", isAdminRequest, message));
|
||||
_testOutputHelperFactory()?.WriteLine(Format("DebugRequestResponse", "Admin[{0}] {1}", isAdminRequest, message));
|
||||
}
|
||||
|
||||
private static string Format(string level, string formatString, params object[] args)
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||
<PackageReference Include="xUnit.abstractions" Version="2.0.3" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="13.1.0" />
|
||||
<Sdk Name="Aspire.AppHost.Sdk" Version="13.4.0" />
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
@@ -19,7 +19,10 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.1.1" />
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="13.4.3" />
|
||||
|
||||
<!-- CVE-2026-48109 -->
|
||||
<PackageReference Include="MessagePack" Version="2.5.302" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.Testing" Version="13.1.1" />
|
||||
<PackageReference Include="Aspire.Hosting.Testing" Version="13.4.3" />
|
||||
<PackageReference Include="Codecov" Version="1.13.0" />
|
||||
<PackageReference Include="coverlet.msbuild" Version="6.0.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
@@ -25,13 +25,16 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="AwesomeAssertions" Version="9.4.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="xunit.v3" Version="3.2.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
<!-- CVE-2026-48109 -->
|
||||
<PackageReference Include="MessagePack" Version="2.5.302" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -92,17 +92,11 @@ public class WireMockServerBuilderExtensionsTests
|
||||
Tag = "latest"
|
||||
});
|
||||
|
||||
var endpointAnnotation = wiremock.Resource.Annotations.OfType<EndpointAnnotation>().FirstOrDefault();
|
||||
endpointAnnotation.Should().BeEquivalentTo(new EndpointAnnotation(
|
||||
protocol: ProtocolType.Tcp,
|
||||
uriScheme: "http",
|
||||
transport: null,
|
||||
name: null,
|
||||
port: port,
|
||||
targetPort: 80,
|
||||
isExternal: null,
|
||||
isProxied: true
|
||||
));
|
||||
var endpointAnnotation = wiremock.Resource.Annotations.OfType<EndpointAnnotation>().First();
|
||||
endpointAnnotation.Protocol.Should().Be(ProtocolType.Tcp);
|
||||
endpointAnnotation.UriScheme.Should().Be("http");
|
||||
endpointAnnotation.Port.Should().Be(port);
|
||||
endpointAnnotation.TargetPort.Should().Be(80);
|
||||
|
||||
wiremock.Resource.Annotations.OfType<EnvironmentCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||
wiremock.Resource.Annotations.OfType<CommandLineArgsCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||
@@ -153,39 +147,24 @@ public class WireMockServerBuilderExtensionsTests
|
||||
endpointAnnotations.Should().HaveCount(3);
|
||||
|
||||
var endpointAnnotationForHttp80 = endpointAnnotations[0];
|
||||
endpointAnnotationForHttp80.Should().BeEquivalentTo(new EndpointAnnotation(
|
||||
protocol: ProtocolType.Tcp,
|
||||
uriScheme: "http",
|
||||
transport: null,
|
||||
name: null,
|
||||
port: null,
|
||||
targetPort: 80,
|
||||
isExternal: null,
|
||||
isProxied: true
|
||||
));
|
||||
endpointAnnotationForHttp80.Protocol.Should().Be(ProtocolType.Tcp);
|
||||
endpointAnnotationForHttp80.UriScheme.Should().Be("http");
|
||||
endpointAnnotationForHttp80.Port.Should().BeNull();
|
||||
endpointAnnotationForHttp80.TargetPort.Should().Be(80);
|
||||
|
||||
var endpointAnnotationForHttpFreePort = endpointAnnotations[1];
|
||||
endpointAnnotationForHttpFreePort.Should().BeEquivalentTo(new EndpointAnnotation(
|
||||
protocol: ProtocolType.Tcp,
|
||||
uriScheme: "http",
|
||||
transport: null,
|
||||
name: $"http-{freePorts[0]}",
|
||||
port: freePorts[0],
|
||||
targetPort: freePorts[0],
|
||||
isExternal: null,
|
||||
isProxied: true
|
||||
));
|
||||
endpointAnnotationForHttpFreePort.Protocol.Should().Be(ProtocolType.Tcp);
|
||||
endpointAnnotationForHttpFreePort.UriScheme.Should().Be("http");
|
||||
endpointAnnotationForHttpFreePort.Name.Should().Be($"http-{freePorts[0]}");
|
||||
endpointAnnotationForHttpFreePort.Port.Should().Be(freePorts[0]);
|
||||
endpointAnnotationForHttpFreePort.TargetPort.Should().Be(freePorts[0]);
|
||||
|
||||
var endpointAnnotationForGrpcFreePort = endpointAnnotations[2];
|
||||
endpointAnnotationForGrpcFreePort.Should().BeEquivalentTo(new EndpointAnnotation(
|
||||
protocol: ProtocolType.Tcp,
|
||||
uriScheme: "grpc",
|
||||
transport: null,
|
||||
name: $"grpc-{freePorts[1]}",
|
||||
port: freePorts[1],
|
||||
targetPort: freePorts[1],
|
||||
isExternal: null,
|
||||
isProxied: true
|
||||
));
|
||||
endpointAnnotationForGrpcFreePort.Protocol.Should().Be(ProtocolType.Tcp);
|
||||
endpointAnnotationForGrpcFreePort.UriScheme.Should().Be("grpc");
|
||||
endpointAnnotationForGrpcFreePort.Name.Should().Be($"grpc-{freePorts[1]}");
|
||||
endpointAnnotationForGrpcFreePort.Port.Should().Be(freePorts[1]);
|
||||
endpointAnnotationForGrpcFreePort.TargetPort.Should().Be(freePorts[1]);
|
||||
|
||||
wiremock.Resource.Annotations.OfType<EnvironmentCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||
wiremock.Resource.Annotations.OfType<CommandLineArgsCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||
|
||||
+1
-1
@@ -16,7 +16,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AwesomeAssertions" Version="9.4.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="AwesomeAssertions" Version="9.4.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.72" />
|
||||
<PackageReference Include="xunit.v3" Version="3.2.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
|
||||
@@ -11,12 +11,12 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="AwesomeAssertions" Version="9.4.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="8.0.1">
|
||||
<PackageReference Include="coverlet.collector" Version="10.0.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageReference Include="WireMock.Net" Version="2.1.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageReference Include="WireMock.Net" Version="2.10.0" />
|
||||
<PackageReference Include="xunit.v3" Version="3.2.2" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
@@ -416,4 +416,20 @@ public class JsonPartialWildcardMatcherTests
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void JsonPartialWildcardMatcher_IsMatch_WithRegexTrue_DateFormat_ShouldMatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new JsonPartialWildcardMatcher(
|
||||
new { date = "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$", id = 1 },
|
||||
ignoreCase: false,
|
||||
regex: true);
|
||||
|
||||
// Act
|
||||
var match = matcher.IsMatch("{\"date\":\"2026-06-09T22:23:18.53421+00:00\",\"id\":1}").Score;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
}
|
||||
@@ -366,17 +366,33 @@ public class SystemTextJsonPartialWildcardMatcherTests
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SystemTextJsonPartialWildcardMatcher_IsMatch_JsonElement_ShouldMatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new SystemTextJsonPartialWildcardMatcher(new { Id = 1, Name = "Test" });
|
||||
[Fact]
|
||||
public void SystemTextJsonPartialWildcardMatcher_IsMatch_JsonElement_ShouldMatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new SystemTextJsonPartialWildcardMatcher(new { Id = 1, Name = "Test" });
|
||||
|
||||
// Act
|
||||
var jsonElement = JsonDocument.Parse("{ \"Id\" : 1, \"Name\" : \"Test\", \"Extra\" : \"value\" }").RootElement;
|
||||
var match = matcher.IsMatch(jsonElement).Score;
|
||||
// Act
|
||||
var jsonElement = JsonDocument.Parse("{ \"Id\" : 1, \"Name\" : \"Test\", \"Extra\" : \"value\" }").RootElement;
|
||||
var match = matcher.IsMatch(jsonElement).Score;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void SystemTextJsonPartialWildcardMatcher_IsMatch_WithRegexTrue_DateFormat_ShouldMatch()
|
||||
{
|
||||
// Assign
|
||||
var matcher = new SystemTextJsonPartialWildcardMatcher(
|
||||
new { date = "^\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}(?:\\.\\d+)?(?:Z|[+-]\\d{2}:\\d{2})$", id = 1 },
|
||||
ignoreCase: false,
|
||||
regex: true);
|
||||
|
||||
// Act
|
||||
var match = matcher.IsMatch("{\"date\":\"2026-06-09T22:23:18.53421+00:00\",\"id\":1}").Score;
|
||||
|
||||
// Assert
|
||||
Assert.Equal(1.0, match);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -50,6 +50,9 @@ public class WireMockMiddlewareTests
|
||||
_guidUtilsMock = new Mock<IGuidUtils>();
|
||||
_guidUtilsMock.Setup(g => g.NewGuid()).Returns(NewGuid);
|
||||
|
||||
var adminPathsMock = new Mock<IAdminPaths>();
|
||||
adminPathsMock.Setup(a => a.Includes(It.IsAny<string?>())).Returns((string? path) => path?.StartsWith("/__admin/") == true);
|
||||
|
||||
_dateTimeUtilsMock = new Mock<IDateTimeUtils>();
|
||||
_dateTimeUtilsMock.Setup(d => d.UtcNow).Returns(UtcNow);
|
||||
|
||||
@@ -89,6 +92,7 @@ public class WireMockMiddlewareTests
|
||||
_sut = new WireMockMiddleware(
|
||||
_ => Task.CompletedTask,
|
||||
_optionsMock.Object,
|
||||
adminPathsMock.Object,
|
||||
_requestMapperMock.Object,
|
||||
_responseMapperMock.Object,
|
||||
_matcherMock.Object,
|
||||
|
||||
@@ -69,7 +69,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.3.0" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.4">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
|
||||
@@ -648,4 +648,24 @@ public class WireMockServerAdminTests(ITestOutputHelper output, ITestContextAcce
|
||||
// Assert
|
||||
settings.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WireMockServer_WithCustomAdminPath_AdminRequestsNotInLogEntries()
|
||||
{
|
||||
// Arrange
|
||||
var cancellationToken = TestContext.Current.CancellationToken;
|
||||
using var server = WireMockServer.Start(w =>
|
||||
{
|
||||
w.Logger = new TestOutputHelperWireMockLogger(output);
|
||||
w.StartAdminInterface = true;
|
||||
w.AdminPath = "/custom/__admin";
|
||||
});
|
||||
var client = server.CreateClient();
|
||||
|
||||
// Act
|
||||
await client.GetAsync($"{server.Url}/custom/__admin/settings", cancellationToken);
|
||||
|
||||
// Assert
|
||||
server.LogEntries.Should().BeEmpty();
|
||||
}
|
||||
}
|
||||
@@ -53,6 +53,81 @@ public partial class WireMockServerTests
|
||||
response.Should().BeEquivalentTo("{\"first_name\":\"John\",\"last_name\":\"Smith\"}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WireMockServer_WithBodyAsJson_WithJsonPartialWildcardMatcher()
|
||||
{
|
||||
// Arrange
|
||||
using var server = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
Logger = new TestOutputHelperWireMockLogger(testOutputHelper)
|
||||
});
|
||||
server
|
||||
.Given(
|
||||
Request.Create()
|
||||
.WithPath("/test")
|
||||
.UsingPost()
|
||||
.WithBody(new JsonPartialWildcardMatcher(
|
||||
new
|
||||
{
|
||||
date = @"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$",
|
||||
id = 1
|
||||
},
|
||||
ignoreCase: true,
|
||||
regex: true
|
||||
)
|
||||
)
|
||||
)
|
||||
.RespondWith(Response.Create().WithStatusCode(200).WithBody("matched"));
|
||||
|
||||
// Act
|
||||
var requestUri = new Uri($"http://localhost:{server.Port}/test");
|
||||
|
||||
var response = await server.CreateClient().PostAsync(requestUri, new StringContent("{\"date\":\"2026-06-09T22:23:18.53421+00:00\",\"id\":1}"), _ct);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WireMockServer_WithBodyAsJson_WithSystemTextJsonPartialWildcardMatcher()
|
||||
{
|
||||
// Arrange
|
||||
using var server = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
Logger = new TestOutputHelperWireMockLogger(testOutputHelper),
|
||||
DefaultJsonSerializer = new SystemTextJsonConverter()
|
||||
});
|
||||
server
|
||||
.Given(
|
||||
Request.Create()
|
||||
.WithPath("/test")
|
||||
.UsingPost()
|
||||
.WithBody(new SystemTextJsonPartialWildcardMatcher(
|
||||
new
|
||||
{
|
||||
date = @"^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(?:\.\d+)?(?:Z|[+-]\d{2}:\d{2})$",
|
||||
id = 1
|
||||
},
|
||||
ignoreCase: true,
|
||||
regex: true
|
||||
)
|
||||
)
|
||||
)
|
||||
.RespondWith(Response.Create().WithStatusCode(200).WithBody("matched"));
|
||||
|
||||
// Act
|
||||
var requestUri = new Uri($"http://localhost:{server.Port}/test");
|
||||
|
||||
var response = await server.CreateClient().PostAsync(requestUri, new StringContent("{\"date\":\"2026-06-09T22:23:18.53421+00:00\",\"id\":1}"), _ct);
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(HttpStatusCode.OK);
|
||||
|
||||
server.Stop();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WireMockServer_WithBodyAsJson_Using_PostAsJsonAsync_And_MultipleJmesPathMatchers_ShouldMatch()
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user