mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-07-29 16:28:42 +02:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
97c8e4a08a | ||
|
|
f5eb01c580 | ||
|
|
8260dba641 | ||
|
|
5e1c126e34 | ||
|
|
ca4eea808e | ||
|
|
5692498ea3 | ||
|
|
d270ad7f4f | ||
|
|
345efe8cfc | ||
|
|
a74468e780 | ||
|
|
041160d824 | ||
|
|
4666757df9 | ||
|
|
49dcbda647 |
@@ -1,3 +1,15 @@
|
|||||||
|
# 2.13.0 (19 July 2026)
|
||||||
|
- [#1488](https://github.com/wiremock/WireMock.Net/pull/1488) - feat(xunit logging): TestOutputHelperWireMockLogger [feature] contributed by [Stepami](https://github.com/Stepami)
|
||||||
|
- [#1490](https://github.com/wiremock/WireMock.Net/pull/1490) - Fix: Fully respect configured custom admin path (merge PR #1483) [feature] contributed by [Copilot](https://github.com/apps/copilot-swe-agent)
|
||||||
|
- [#1482](https://github.com/wiremock/WireMock.Net/issues/1482) - WireMock.Minimal.Owin does not respect custom pathing for determining admin paths [bug]
|
||||||
|
|
||||||
|
# 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)
|
# 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)
|
- [#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)
|
- [#1476](https://github.com/wiremock/WireMock.Net/pull/1476) - Fix BodyParser [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>2.11.0</VersionPrefix>
|
<VersionPrefix>2.13.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>
|
||||||
@@ -51,8 +51,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2025.2.4" PrivateAssets="All" />
|
<PackageReference Include="JetBrains.Annotations" Version="2026.2.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.300" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.301" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
rem https://github.com/StefH/GitHubReleaseNotes
|
rem https://github.com/StefH/GitHubReleaseNotes
|
||||||
|
|
||||||
SET version=2.11.0
|
SET version=2.13.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,6 +1,6 @@
|
|||||||
# 2.11.0 (12 June 2026)
|
# 2.13.0 (19 July 2026)
|
||||||
- #1475 Update NuGet packages (Aspire, MessagePack and more) [security]
|
- #1488 feat(xunit logging): TestOutputHelperWireMockLogger [feature]
|
||||||
- #1476 Fix BodyParser [bug]
|
- #1490 Fix: Fully respect configured custom admin path (merge PR #1483) [feature]
|
||||||
- #1473 JsonPartialWildCardMatcher With DateTime Regex Stopped Matching (Regression?) [bug]
|
- #1482 WireMock.Minimal.Owin does not respect custom pathing for determining admin paths [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
|
||||||
@@ -1,3 +1,9 @@
|
|||||||
|
parameters:
|
||||||
|
- name: runWindowsReleaseToMyGet
|
||||||
|
displayName: Run Windows Release to MyGet
|
||||||
|
type: boolean
|
||||||
|
default: false
|
||||||
|
|
||||||
variables:
|
variables:
|
||||||
Prerelease: 'ci'
|
Prerelease: 'ci'
|
||||||
buildId: "1$(Build.BuildId)"
|
buildId: "1$(Build.BuildId)"
|
||||||
@@ -131,6 +137,7 @@ jobs:
|
|||||||
|
|
||||||
- job: Windows_Release_to_MyGet
|
- job: Windows_Release_to_MyGet
|
||||||
dependsOn: Windows_Build_Test
|
dependsOn: Windows_Build_Test
|
||||||
|
condition: and(succeeded(), ${{ parameters.runWindowsReleaseToMyGet }})
|
||||||
|
|
||||||
pool:
|
pool:
|
||||||
vmImage: 'windows-2025'
|
vmImage: 'windows-2025'
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace WireMock.Net.Console.MimePart;
|
|||||||
|
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
|
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly()!);
|
||||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
||||||
|
|
||||||
static async Task Main(params string[] args)
|
static async Task Main(params string[] args)
|
||||||
|
|||||||
@@ -1115,7 +1115,7 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
{
|
{
|
||||||
BodyData = new BodyData
|
BodyData = new BodyData
|
||||||
{
|
{
|
||||||
BodyAsString = "random200or505:" + code + ", HeadersFromRequest = " + string.Join(",", request.Headers),
|
BodyAsString = "random200or505:" + code + ", HeadersFromRequest = " + request.Headers != null ? string.Join(",", request.Headers!.Select(h => $"{h.Key}:{h.Value}")) : "none",
|
||||||
DetectedBodyType = BodyType.String,
|
DetectedBodyType = BodyType.String,
|
||||||
},
|
},
|
||||||
StatusCode = code
|
StatusCode = code
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System.IO;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using log4net;
|
using log4net;
|
||||||
using log4net.Config;
|
using log4net.Config;
|
||||||
using log4net.Repository;
|
using log4net.Repository;
|
||||||
@@ -12,8 +10,7 @@ namespace WireMock.Net.Console.NET8;
|
|||||||
|
|
||||||
static class Program
|
static class Program
|
||||||
{
|
{
|
||||||
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
|
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly()!);
|
||||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
|
||||||
|
|
||||||
static async Task Main(params string[] args)
|
static async Task Main(params string[] args)
|
||||||
{
|
{
|
||||||
|
|||||||
+1
-1
@@ -16,7 +16,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="WireMock.Net" Version="2.10.0" />
|
<PackageReference Include="WireMock.Net" Version="2.12.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
+2
-5
@@ -6,7 +6,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<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.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net.OpenApiParser\WireMock.Net.OpenApiParser.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net.OpenApiParser\WireMock.Net.OpenApiParser.csproj" />
|
||||||
@@ -14,10 +14,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
||||||
<PackageReference Include="Microsoft.OpenApi" Version="2.3.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.OpenApi" Version="3.7.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" />-->
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -36,12 +36,6 @@
|
|||||||
<StartupObject>Wiremock.Net.Service.Program</StartupObject>
|
<StartupObject>Wiremock.Net.Service.Program</StartupObject>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="SimMetrics.Net, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c58dc06d59f3391b, processorArchitecture=MSIL">
|
|
||||||
<HintPath>..\..\packages\SimMetrics.Net.1.0.5\lib\net45\SimMetrics.Net.dll</HintPath>
|
|
||||||
</Reference>
|
|
||||||
<Reference Include="System" />
|
<Reference Include="System" />
|
||||||
<Reference Include="System.Configuration" />
|
<Reference Include="System.Configuration" />
|
||||||
<Reference Include="System.Configuration.Install" />
|
<Reference Include="System.Configuration.Install" />
|
||||||
@@ -91,13 +85,13 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="log4net">
|
<PackageReference Include="log4net">
|
||||||
<Version>3.3.0</Version>
|
<Version>3.3.2</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Core">
|
<PackageReference Include="Microsoft.AspNetCore.Server.Kestrel.Core">
|
||||||
<Version>2.3.9</Version>
|
<Version>2.3.11</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="WireMock.Net">
|
<PackageReference Include="WireMock.Net">
|
||||||
<Version>2.10.0</Version>
|
<Version>2.12.0</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System.Linq;
|
|
||||||
|
|
||||||
namespace WireMock.Types;
|
namespace WireMock.Types;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// A special List which overrides the ToString() to return first value.
|
/// A special List which overrides the ToString() to return first value in case of a single element.
|
||||||
|
/// Else it will return a comma separated list of all values.
|
||||||
|
/// If null or empty, it will return an empty string.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <typeparam name="T">The generic type</typeparam>
|
/// <typeparam name="T">The generic type</typeparam>
|
||||||
/// <seealso cref="List{T}" />
|
/// <seealso cref="List{T}" />
|
||||||
@@ -62,10 +62,10 @@ public class WireMockList<T> : List<T>
|
|||||||
return strValue;
|
return strValue;
|
||||||
}
|
}
|
||||||
|
|
||||||
return this[0]?.ToString();
|
return this[0]?.ToString() ?? string.Empty;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
var strings = this.Select(x => x as string ?? x?.ToString());
|
var strings = this.Select(x => x as string ?? x?.ToString() ?? string.Empty);
|
||||||
return string.Join(", ", strings);
|
return string.Join(", ", strings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
// 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) => path?.StartsWith($"{_prefix}/") ?? false;
|
||||||
|
|
||||||
|
public override string ToString() => _prefix;
|
||||||
|
}
|
||||||
@@ -66,6 +66,7 @@ internal partial class AspNetCoreSelfHost
|
|||||||
.ConfigureServices(services =>
|
.ConfigureServices(services =>
|
||||||
{
|
{
|
||||||
services.AddSingleton(_wireMockMiddlewareOptions);
|
services.AddSingleton(_wireMockMiddlewareOptions);
|
||||||
|
services.AddSingleton(_wireMockMiddlewareOptions.AdminPaths);
|
||||||
services.AddSingleton<IMappingMatcher, MappingMatcher>();
|
services.AddSingleton<IMappingMatcher, MappingMatcher>();
|
||||||
services.AddSingleton<IRandomizerDoubleBetween0And1, RandomizerDoubleBetween0And1>();
|
services.AddSingleton<IRandomizerDoubleBetween0And1, RandomizerDoubleBetween0And1>();
|
||||||
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
||||||
|
|||||||
@@ -0,0 +1,48 @@
|
|||||||
|
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.
|
/// Set this property to customize how objects are serialized to and deserialized from JSON during mapping.
|
||||||
/// </remarks>
|
/// </remarks>
|
||||||
IJsonConverter DefaultJsonSerializer { get; set; }
|
IJsonConverter DefaultJsonSerializer { get; set; }
|
||||||
|
|
||||||
|
IAdminPaths AdminPaths { get; set; }
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ internal class WireMockMiddleware(
|
|||||||
RequestDelegate next,
|
RequestDelegate next,
|
||||||
#pragma warning restore CS9113 // Parameter is unread.
|
#pragma warning restore CS9113 // Parameter is unread.
|
||||||
IWireMockMiddlewareOptions options,
|
IWireMockMiddlewareOptions options,
|
||||||
|
IAdminPaths adminPaths,
|
||||||
IOwinRequestMapper requestMapper,
|
IOwinRequestMapper requestMapper,
|
||||||
IOwinResponseMapper responseMapper,
|
IOwinResponseMapper responseMapper,
|
||||||
IMappingMatcher mappingMatcher,
|
IMappingMatcher mappingMatcher,
|
||||||
@@ -64,7 +65,7 @@ internal class WireMockMiddleware(
|
|||||||
Activity? activity = null;
|
Activity? activity = null;
|
||||||
|
|
||||||
// Check if we should trace this request (optionally exclude admin requests)
|
// 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)
|
if (shouldTrace)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -9,39 +9,44 @@ using WireMock.Util;
|
|||||||
namespace WireMock.Owin;
|
namespace WireMock.Owin;
|
||||||
|
|
||||||
internal class WireMockMiddlewareLogger(
|
internal class WireMockMiddlewareLogger(
|
||||||
IWireMockMiddlewareOptions _options,
|
IWireMockMiddlewareOptions options,
|
||||||
LogEntryMapper _logEntryMapper,
|
LogEntryMapper logEntryMapper,
|
||||||
IGuidUtils _guidUtils
|
IGuidUtils guidUtils,
|
||||||
|
IAdminPaths adminPaths,
|
||||||
|
IDateTimeUtils dateTimeUtils
|
||||||
) : IWireMockMiddlewareLogger
|
) : IWireMockMiddlewareLogger
|
||||||
{
|
{
|
||||||
public void LogRequestAndResponse(bool logRequest, RequestMessage request, IResponseMessage? response, MappingMatcherResult? match, MappingMatcherResult? partialMatch, Activity? activity)
|
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
|
var logEntry = new LogEntry
|
||||||
{
|
{
|
||||||
Guid = _guidUtils.NewGuid(),
|
Guid = guidUtils.NewGuid(),
|
||||||
RequestMessage = request,
|
RequestMessage = request,
|
||||||
ResponseMessage = response,
|
ResponseMessage = response,
|
||||||
|
|
||||||
MappingGuid = match?.Mapping?.Guid,
|
MappingGuid = mapping?.Guid,
|
||||||
MappingTitle = match?.Mapping?.Title,
|
MappingTitle = mapping?.Title,
|
||||||
RequestMatchResult = match?.RequestMatchResult,
|
RequestMatchResult = match?.RequestMatchResult,
|
||||||
|
|
||||||
PartialMappingGuid = partialMatch?.Mapping?.Guid,
|
PartialMappingGuid = partialMapping?.Guid,
|
||||||
PartialMappingTitle = partialMatch?.Mapping?.Title,
|
PartialMappingTitle = partialMapping?.Title,
|
||||||
PartialMatchResult = partialMatch?.RequestMatchResult
|
PartialMatchResult = partialMatch?.RequestMatchResult
|
||||||
};
|
};
|
||||||
|
|
||||||
WireMockActivitySource.EnrichWithLogEntry(activity, logEntry, _options.ActivityTracingOptions);
|
WireMockActivitySource.EnrichWithLogEntry(activity, logEntry, options.ActivityTracingOptions);
|
||||||
activity?.Dispose();
|
activity?.Dispose();
|
||||||
|
|
||||||
LogLogEntry(logEntry, logRequest);
|
LogLogEntry(logEntry, logRequest);
|
||||||
|
|
||||||
try
|
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";
|
var filename = $"{logEntry.Guid}.LogEntry.json";
|
||||||
_options.FileSystemHandler?.WriteUnmatchedRequest(filename, _options.DefaultJsonSerializer.Serialize(logEntry));
|
options.FileSystemHandler?.WriteUnmatchedRequest(filename, options.DefaultJsonSerializer.Serialize(logEntry));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
@@ -52,34 +57,35 @@ internal class WireMockMiddlewareLogger(
|
|||||||
|
|
||||||
public void LogLogEntry(LogEntry entry, bool addRequest)
|
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 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);
|
TryAddLogEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// In case MaxRequestLogCount has a value greater than 0, try to delete existing request logs based on the count.
|
// 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
|
foreach (var logEntry in logEntries
|
||||||
.OrderBy(le => le.RequestMessage?.DateTime ?? le.ResponseMessage?.DateTime)
|
.OrderBy(le => le.RequestMessage?.DateTime ?? le.ResponseMessage?.DateTime)
|
||||||
.Take(logEntries.Count - _options.MaxRequestLogCount.Value))
|
.Take(logEntries.Count - options.MaxRequestLogCount.Value))
|
||||||
{
|
{
|
||||||
TryRemoveLogEntry(logEntry);
|
TryRemoveLogEntry(logEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the date.
|
// 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))
|
foreach (var logEntry in logEntries.Where(le => le.RequestMessage?.DateTime < checkTime || le.ResponseMessage?.DateTime < checkTime))
|
||||||
{
|
{
|
||||||
TryRemoveLogEntry(logEntry);
|
TryRemoveLogEntry(logEntry);
|
||||||
@@ -91,7 +97,7 @@ internal class WireMockMiddlewareLogger(
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_options.LogEntries.Add(logEntry);
|
options.LogEntries.Add(logEntry);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
@@ -103,7 +109,7 @@ internal class WireMockMiddlewareLogger(
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
_options.LogEntries.Remove(logEntry);
|
options.LogEntries.Remove(logEntry);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -115,4 +115,7 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IJsonConverter DefaultJsonSerializer { get; set; } = new NewtonsoftJsonConverter();
|
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.QueryParameterMultipleValueSupport = settings.QueryParameterMultipleValueSupport;
|
||||||
options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
|
options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
|
||||||
options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
||||||
|
options.AdminPaths = new AdminPaths(settings.AdminPath);
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
options.AdditionalServiceRegistration = settings.AdditionalServiceRegistration;
|
options.AdditionalServiceRegistration = settings.AdditionalServiceRegistration;
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ using WireMock.RequestBuilders;
|
|||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
using WireMock.Transformers;
|
using WireMock.Transformers;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
|
||||||
|
|
||||||
namespace WireMock.ResponseBuilders;
|
namespace WireMock.ResponseBuilders;
|
||||||
|
|
||||||
@@ -86,7 +85,11 @@ public partial class Response : IResponseBuilder
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public static IResponseBuilder Create(ResponseMessage? responseMessage = null)
|
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);
|
return new Response(message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -19,7 +19,6 @@ using WireMock.Owin;
|
|||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
using WireMock.ResponseProviders;
|
using WireMock.ResponseProviders;
|
||||||
using WireMock.Serialization;
|
using WireMock.Serialization;
|
||||||
using WireMock.Settings;
|
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
@@ -28,50 +27,16 @@ namespace WireMock.Server;
|
|||||||
public partial class WireMockServer
|
public partial class WireMockServer
|
||||||
{
|
{
|
||||||
private const int EnhancedFileSystemWatcherTimeoutMs = 1000;
|
private const int EnhancedFileSystemWatcherTimeoutMs = 1000;
|
||||||
private const string DefaultAdminPathPrefix = "/__admin";
|
|
||||||
private const string QueryParamReloadStaticMappings = "reloadStaticMappings";
|
private const string QueryParamReloadStaticMappings = "reloadStaticMappings";
|
||||||
private static readonly Guid ProxyMappingGuid = new("e59914fd-782e-428e-91c1-4810ffb86567");
|
private static readonly Guid ProxyMappingGuid = new("e59914fd-782e-428e-91c1-4810ffb86567");
|
||||||
private static readonly RegexMatcher AdminRequestContentTypeJson = new ContentTypeMatcher(WireMockConstants.ContentTypeJson, true);
|
private static readonly RegexMatcher AdminRequestContentTypeJson = new ContentTypeMatcher(WireMockConstants.ContentTypeJson, true);
|
||||||
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
||||||
private AdminPaths? _adminPaths;
|
private IAdminPaths? _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\\/.+$");
|
|
||||||
}
|
|
||||||
|
|
||||||
#region InitAdmin
|
#region InitAdmin
|
||||||
private void InitAdmin()
|
private void InitAdmin()
|
||||||
{
|
{
|
||||||
_adminPaths = new AdminPaths(_settings);
|
_adminPaths = _options.AdminPaths;
|
||||||
|
|
||||||
// __admin/health
|
// __admin/health
|
||||||
Given(Request.Create().WithPath(_adminPaths.Health).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(HealthGet));
|
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))
|
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 { })
|
if (entry is { })
|
||||||
{
|
{
|
||||||
var model = new LogEntryMapper(_options).Map(entry);
|
var model = new LogEntryMapper(_options).Map(entry);
|
||||||
@@ -660,7 +625,7 @@ public partial class WireMockServer
|
|||||||
{
|
{
|
||||||
var logEntryMapper = new LogEntryMapper(_options);
|
var logEntryMapper = new LogEntryMapper(_options);
|
||||||
var result = LogEntries
|
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);
|
.Select(logEntryMapper.Map);
|
||||||
|
|
||||||
return ToJson(result);
|
return ToJson(result);
|
||||||
@@ -682,7 +647,7 @@ public partial class WireMockServer
|
|||||||
var request = (Request)InitRequestBuilder(requestModel);
|
var request = (Request)InitRequestBuilder(requestModel);
|
||||||
|
|
||||||
var dict = new Dictionary<ILogEntry, RequestMatchResult>();
|
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();
|
var requestMatchResult = new RequestMatchResult();
|
||||||
if (request.GetMatchingScore(logEntry.RequestMessage!, requestMatchResult) > MatchScores.AlmostPerfect)
|
if (request.GetMatchingScore(logEntry.RequestMessage!, requestMatchResult) > MatchScores.AlmostPerfect)
|
||||||
@@ -704,7 +669,7 @@ public partial class WireMockServer
|
|||||||
Guid.TryParse(value.ToString(), out var mappingGuid)
|
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 logEntryMapper = new LogEntryMapper(_options);
|
||||||
var result = logEntries.Select(logEntryMapper.Map);
|
var result = logEntries.Select(logEntryMapper.Map);
|
||||||
return ToJson(result);
|
return ToJson(result);
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -43,7 +43,7 @@
|
|||||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||||
<PackageReference Include="TinyMapper.Signed" Version="4.0.0" />
|
<PackageReference Include="TinyMapper.Signed" Version="4.0.0" />
|
||||||
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.34.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>
|
||||||
|
|
||||||
<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;
|
openApiMediaType = null;
|
||||||
contentType = null;
|
contentType = null;
|
||||||
|
|||||||
@@ -40,21 +40,21 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.4" />
|
||||||
<PackageReference Include="RamlToOpenApiConverter.SourceOnly" Version="0.11.0" />
|
<PackageReference Include="RamlToOpenApiConverter.SourceOnly" Version="0.21.0" />
|
||||||
<PackageReference Include="YamlDotNet" Version="16.3.0" />
|
<PackageReference Include="YamlDotNet" Version="18.1.0" />
|
||||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.19.1" />
|
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.19.1" />
|
||||||
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
<PackageReference Include="Stef.Validation" Version="0.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
|
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
|
||||||
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="2.3.0" />
|
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="3.7.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
||||||
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.43" PrivateAssets="All" />
|
<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" Version="3.7.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="2.3.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="3.7.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="SharpYaml" Version="2.1.3" />
|
<PackageReference Include="SharpYaml" Version="2.1.4" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Admin.Requests;
|
using WireMock.Admin.Requests;
|
||||||
@@ -14,51 +13,61 @@ namespace WireMock.Net.Xunit;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class TestOutputHelperWireMockLogger : IWireMockLogger
|
public sealed class TestOutputHelperWireMockLogger : IWireMockLogger
|
||||||
{
|
{
|
||||||
private readonly ITestOutputHelper _testOutputHelper;
|
private readonly Func<ITestOutputHelper?> _testOutputHelperFactory;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new instance on the <see cref="TestOutputHelperWireMockLogger"/>.
|
/// Create a new instance on the <see cref="TestOutputHelperWireMockLogger"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="testOutputHelper">Represents a class which can be used to provide test output.</param>
|
/// <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 />
|
/// <inheritdoc />
|
||||||
public void Debug(string formatString, params object[] args)
|
public void Debug(string formatString, params object[] args)
|
||||||
{
|
{
|
||||||
_testOutputHelper.WriteLine(Format("Debug", formatString, args));
|
_testOutputHelperFactory()?.WriteLine(Format("Debug", formatString, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Info(string formatString, params object[] args)
|
public void Info(string formatString, params object[] args)
|
||||||
{
|
{
|
||||||
_testOutputHelper.WriteLine(Format("Info", formatString, args));
|
_testOutputHelperFactory()?.WriteLine(Format("Info", formatString, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Warn(string formatString, params object[] args)
|
public void Warn(string formatString, params object[] args)
|
||||||
{
|
{
|
||||||
_testOutputHelper.WriteLine(Format("Warning", formatString, args));
|
_testOutputHelperFactory()?.WriteLine(Format("Warning", formatString, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Error(string formatString, params object[] args)
|
public void Error(string formatString, params object[] args)
|
||||||
{
|
{
|
||||||
_testOutputHelper.WriteLine(Format("Error", formatString, args));
|
_testOutputHelperFactory()?.WriteLine(Format("Error", formatString, args));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public void Error(string message, Exception exception)
|
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)
|
if (exception is AggregateException ae)
|
||||||
{
|
{
|
||||||
ae.Handle(ex =>
|
ae.Handle(ex =>
|
||||||
{
|
{
|
||||||
_testOutputHelper.WriteLine(Format("Error", "Exception {0}", ex));
|
_testOutputHelperFactory()?.WriteLine(Format("Error", "Exception {0}", ex));
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -72,7 +81,7 @@ public sealed class TestOutputHelperWireMockLogger : IWireMockLogger
|
|||||||
Formatting = Formatting.Indented,
|
Formatting = Formatting.Indented,
|
||||||
NullValueHandling = NullValueHandling.Ignore
|
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)
|
private static string Format(string level, string formatString, params object[] args)
|
||||||
|
|||||||
@@ -15,8 +15,8 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.6.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="18.8.1" />
|
||||||
<PackageReference Include="WireMock.Net" Version="2.10.0" />
|
<PackageReference Include="WireMock.Net" Version="2.12.0" />
|
||||||
<PackageReference Include="xunit.v3" Version="3.2.2" />
|
<PackageReference Include="xunit.v3" Version="3.2.2" />
|
||||||
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
<PackageReference Include="xunit.runner.visualstudio" Version="3.1.5">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
@@ -29,13 +29,13 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Update="JetBrains.Annotations" Version="2025.2.4" />
|
<!--<PackageReference Update="JetBrains.Annotations" Version="2025.2.4" />-->
|
||||||
<PackageReference Include="OpenTelemetry" Version="1.15.3" />
|
<PackageReference Include="OpenTelemetry" Version="1.17.0" />
|
||||||
<PackageReference Include="OpenTelemetry.Api" Version="1.15.3" />
|
<PackageReference Include="OpenTelemetry.Api" Version="1.17.0" />
|
||||||
<PackageReference Include="OpenTelemetry.Api.ProviderBuilderExtensions" Version="1.15.3" />
|
<PackageReference Include="OpenTelemetry.Api.ProviderBuilderExtensions" Version="1.17.0" />
|
||||||
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.15.3" />
|
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.17.0" />
|
||||||
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.15.3" />
|
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.17.0" />
|
||||||
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.15.2" />
|
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.17.0" />
|
||||||
<PackageReference Update="SonarAnalyzer.CSharp" Version="10.11.0.117924" />
|
<PackageReference Update="SonarAnalyzer.CSharp" Version="10.11.0.117924" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,411 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using WireMock.Types;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Tests.Abstractions;
|
||||||
|
|
||||||
|
public class WireMockListTests
|
||||||
|
{
|
||||||
|
#region String Generic Type Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_Constructor_Empty_ShouldCreateEmptyList()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var list = new WireMockList<string>();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().BeEmpty();
|
||||||
|
list.Count.Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_Constructor_WithSingleString_ShouldCreateListWithOneElement()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var value = "test";
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var list = new WireMockList<string>(value);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(1);
|
||||||
|
list[0].Should().Be("test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_Constructor_WithMultipleStrings_ShouldCreateListWithAllElements()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var values = new[] { "value1", "value2", "value3" };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var list = new WireMockList<string>(values);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(3);
|
||||||
|
list.Should().ContainInOrder("value1", "value2", "value3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_Constructor_WithIEnumerable_ShouldCreateListWithAllElements()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var values = new List<string> { "a", "b", "c" };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var list = new WireMockList<string>(values);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(3);
|
||||||
|
list.Should().ContainInOrder("a", "b", "c");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_ToString_WhenEmpty_ShouldReturnEmptyString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<string>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_ToString_WhenSingleElement_ShouldReturnElementValue()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<string>("singleValue");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be("singleValue");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_ToString_WhenMultipleElements_ShouldReturnCommaSeparatedValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<string>("value1", "value2", "value3");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be("value1, value2, value3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_ImplicitOperator_WithSingleValue_ShouldCreateList()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
WireMockList<string> list = "testValue";
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(1);
|
||||||
|
list[0].Should().Be("testValue");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_ImplicitOperator_WithArray_ShouldCreateList()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var values = new[] { "first", "second", "third" };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
WireMockList<string> list = values;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(3);
|
||||||
|
list.Should().ContainInOrder("first", "second", "third");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Object Generic Type Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_Constructor_Empty_ShouldCreateEmptyList()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var list = new WireMockList<object>();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().BeEmpty();
|
||||||
|
list.Count.Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_Constructor_WithSingleObject_ShouldCreateListWithOneElement()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var obj = new { Name = "Test", Value = 123 };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var list = new WireMockList<object>(obj);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(1);
|
||||||
|
list[0].Should().Be(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_Constructor_WithMultipleObjects_ShouldCreateListWithAllElements()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var obj1 = new object();
|
||||||
|
var obj2 = new object();
|
||||||
|
var obj3 = new object();
|
||||||
|
var values = new[] { obj1, obj2, obj3 };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var list = new WireMockList<object>(values);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(3);
|
||||||
|
list.Should().ContainInOrder(obj1, obj2, obj3);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_Constructor_WithIEnumerable_ShouldCreateListWithAllElements()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var values = new List<object?>
|
||||||
|
{
|
||||||
|
"string",
|
||||||
|
123,
|
||||||
|
45.67,
|
||||||
|
true,
|
||||||
|
null
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var list = new WireMockList<object?>(values);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(5);
|
||||||
|
list.Should().ContainInOrder("string", 123, 45.67, true, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ToString_WhenEmpty_ShouldReturnEmptyString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<object>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ToString_WhenSingleString_ShouldReturnString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<object>("singleString");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be("singleString");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ToString_WhenSingleObject_ShouldReturnObjectToString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var obj = new { Name = "Test" };
|
||||||
|
var list = new WireMockList<object>(obj);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Contain("Name");
|
||||||
|
result.Should().Contain("Test");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ToString_WhenSingleInt_ShouldReturnIntAsString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<object>(42);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be("42");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ToString_WhenMultipleElements_ShouldReturnCommaSeparatedValues()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<object>("text", 123, 45.67);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be($"text, 123, {45.67}");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ToString_WithMixedTypes_ShouldReturnCommaSeparatedStringRepresentation()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<object>
|
||||||
|
{
|
||||||
|
"string",
|
||||||
|
123,
|
||||||
|
45.67,
|
||||||
|
true
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be($"string, 123, {45.67}, True");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ToString_WithNullValue_ShouldReturnEmptyStringForNull()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<object?>
|
||||||
|
{
|
||||||
|
"value1",
|
||||||
|
null,
|
||||||
|
"value3"
|
||||||
|
};
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be("value1, , value3");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ImplicitOperator_WithSingleValue_ShouldCreateList()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var obj = new { Id = 1 };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
WireMockList<object> list = obj;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(1);
|
||||||
|
list[0].Should().Be(obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ImplicitOperator_WithArray_ShouldCreateList()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var values = new object[] { "first", 2, 3.0 };
|
||||||
|
|
||||||
|
// Act
|
||||||
|
WireMockList<object> list = values;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(3);
|
||||||
|
list.Should().ContainInOrder("first", 2, 3.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region List Operations Tests
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_Add_ShouldAddElement()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<string>("initial");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
list.Add("new");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(2);
|
||||||
|
list[1].Should().Be("new");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_Remove_ShouldRemoveElement()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<string>("value1", "value2", "value3");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var removed = list.Remove("value2");
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
removed.Should().BeTrue();
|
||||||
|
list.Should().HaveCount(2);
|
||||||
|
list.Should().ContainInOrder("value1", "value3");
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
|
||||||
|
#region Edge Cases
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_ToString_WithEmptyString_ShouldReturnEmptyString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var list = new WireMockList<string>("");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be("");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfString_Constructor_WithNull_ShouldThrow()
|
||||||
|
{
|
||||||
|
// Act & Assert
|
||||||
|
var act = () => new WireMockList<string?>(null!);
|
||||||
|
act.Should().Throw<ArgumentNullException>();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ImplicitOperator_WithNull_ShouldCreateListWithNullElement()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
WireMockList<object> list = (null as object)!;
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
list.Should().HaveCount(1);
|
||||||
|
list[0].Should().BeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockListOfObject_ToString_WhenSingleNullObject_ShouldReturnEmptyString()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
object? nullObj = null;
|
||||||
|
var list = new WireMockList<object>(nullObj!);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var result = list.ToString();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be(string.Empty);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endregion
|
||||||
|
}
|
||||||
@@ -1,16 +1,16 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using JsonConverter.Newtonsoft.Json;
|
||||||
|
using JsonConverter.System.Text.Json;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.Extensions.Primitives;
|
||||||
using Moq;
|
using Moq;
|
||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
|
using WireMock.Owin;
|
||||||
using WireMock.Owin.Mappers;
|
using WireMock.Owin.Mappers;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
using WireMock.Owin;
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using Microsoft.Extensions.Primitives;
|
|
||||||
using JsonConverter.Newtonsoft.Json;
|
|
||||||
using JsonConverter.System.Text.Json;
|
|
||||||
|
|
||||||
namespace WireMock.Net.Tests.Owin.Mappers;
|
namespace WireMock.Net.Tests.Owin.Mappers;
|
||||||
|
|
||||||
@@ -40,11 +40,11 @@ public class OwinResponseMapperTests
|
|||||||
|
|
||||||
_headers = new Mock<IHeaderDictionary>();
|
_headers = new Mock<IHeaderDictionary>();
|
||||||
_headers.SetupAllProperties();
|
_headers.SetupAllProperties();
|
||||||
#if NET452
|
|
||||||
_headers.Setup(h => h.AppendValues(It.IsAny<string>(), It.IsAny<string[]>()));
|
// Extension methods(here: HeaderDictionaryExtensions.Append) may not be used in setup / verification expressions.
|
||||||
#else
|
#pragma warning disable ASP0019
|
||||||
_headers.Setup(h => h.Add(It.IsAny<string>(), It.IsAny<StringValues>()));
|
_headers.Setup(h => h.Add(It.IsAny<string>(), It.IsAny<StringValues>()));
|
||||||
#endif
|
#pragma warning restore ASP0019
|
||||||
|
|
||||||
_responseMock = new Mock<HttpResponse>();
|
_responseMock = new Mock<HttpResponse>();
|
||||||
_responseMock.SetupAllProperties();
|
_responseMock.SetupAllProperties();
|
||||||
@@ -238,12 +238,8 @@ public class OwinResponseMapperTests
|
|||||||
await _sut.MapAsync(responseMessage, _responseMock.Object);
|
await _sut.MapAsync(responseMessage, _responseMock.Object);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
#if NET452
|
|
||||||
_headers.Verify(h => h.AppendValues("h", new string[] { "x", "y" }), Times.Once);
|
|
||||||
#else
|
|
||||||
var v = new StringValues();
|
var v = new StringValues();
|
||||||
_headers.Verify(h => h.TryGetValue("h", out v), Times.Once);
|
_headers.Verify(h => h.TryGetValue("h", out v), Times.Once);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -50,6 +50,9 @@ public class WireMockMiddlewareTests
|
|||||||
_guidUtilsMock = new Mock<IGuidUtils>();
|
_guidUtilsMock = new Mock<IGuidUtils>();
|
||||||
_guidUtilsMock.Setup(g => g.NewGuid()).Returns(NewGuid);
|
_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 = new Mock<IDateTimeUtils>();
|
||||||
_dateTimeUtilsMock.Setup(d => d.UtcNow).Returns(UtcNow);
|
_dateTimeUtilsMock.Setup(d => d.UtcNow).Returns(UtcNow);
|
||||||
|
|
||||||
@@ -89,6 +92,7 @@ public class WireMockMiddlewareTests
|
|||||||
_sut = new WireMockMiddleware(
|
_sut = new WireMockMiddleware(
|
||||||
_ => Task.CompletedTask,
|
_ => Task.CompletedTask,
|
||||||
_optionsMock.Object,
|
_optionsMock.Object,
|
||||||
|
adminPathsMock.Object,
|
||||||
_requestMapperMock.Object,
|
_requestMapperMock.Object,
|
||||||
_responseMapperMock.Object,
|
_responseMapperMock.Object,
|
||||||
_matcherMock.Object,
|
_matcherMock.Object,
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
|
|
||||||
@@ -17,7 +16,7 @@ public class RequestBuilderUsingMethodTests
|
|||||||
// Assert
|
// Assert
|
||||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||||
matchers.Count.Should().Be(1);
|
matchers.Count.Should().Be(1);
|
||||||
(matchers[0] as RequestMessageMethodMatcher).Methods.Should().ContainSingle("CONNECT");
|
matchers[0].Should().BeOfType<RequestMessageMethodMatcher>().Which.Methods.Should().ContainSingle("CONNECT");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -29,7 +28,7 @@ public class RequestBuilderUsingMethodTests
|
|||||||
// Assert
|
// Assert
|
||||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||||
matchers.Count.Should().Be(1);
|
matchers.Count.Should().Be(1);
|
||||||
(matchers[0] as RequestMessageMethodMatcher).Methods.Should().ContainSingle("OPTIONS");
|
matchers[0].Should().BeOfType<RequestMessageMethodMatcher>().Which.Methods.Should().ContainSingle("OPTIONS");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -41,7 +40,7 @@ public class RequestBuilderUsingMethodTests
|
|||||||
// Assert
|
// Assert
|
||||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||||
matchers.Count.Should().Be(1);
|
matchers.Count.Should().Be(1);
|
||||||
(matchers[0] as RequestMessageMethodMatcher).Methods.Should().ContainSingle("PATCH");
|
matchers[0].Should().BeOfType<RequestMessageMethodMatcher>().Which.Methods.Should().ContainSingle("PATCH");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
@@ -53,7 +52,7 @@ public class RequestBuilderUsingMethodTests
|
|||||||
// Assert
|
// Assert
|
||||||
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
var matchers = requestBuilder.GetPrivateFieldValue<IList<IRequestMatcher>>("_requestMatchers");
|
||||||
matchers.Count.Should().Be(1);
|
matchers.Count.Should().Be(1);
|
||||||
(matchers[0] as RequestMessageMethodMatcher).Methods.Should().ContainSingle("TRACE");
|
matchers[0].Should().BeOfType<RequestMessageMethodMatcher>().Which.Methods.Should().ContainSingle("TRACE");
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -158,4 +158,8 @@
|
|||||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Folder Include="Types\" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -648,4 +648,24 @@ public class WireMockServerAdminTests(ITestOutputHelper output, ITestContextAcce
|
|||||||
// Assert
|
// Assert
|
||||||
settings.Should().NotBeNull();
|
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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user