mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-27 19:27:42 +02:00
Compare commits
12 Commits
1.16.0
...
1341-mappi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
197a211a52 | ||
|
|
3cfeec6035 | ||
|
|
b57d5e7548 | ||
|
|
36b89afce5 | ||
|
|
e2acac55a4 | ||
|
|
ceabd27ce0 | ||
|
|
f8e2c7ee90 | ||
|
|
c25d8f33d2 | ||
|
|
6da190e596 | ||
|
|
44388ce80d | ||
|
|
5e25ca767d | ||
|
|
0cc583a4a3 |
17
CHANGELOG.md
17
CHANGELOG.md
@@ -1,3 +1,20 @@
|
|||||||
|
# 1.19.0 (12 December 2025)
|
||||||
|
- [#1391](https://github.com/wiremock/WireMock.Net/pull/1391) - Update WireMockContainerBuilder (WithImage and WithCustomImage) [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#1392](https://github.com/wiremock/WireMock.Net/pull/1392) - WireMockContainerBuilder: allow all docker images named wiremock [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#1390](https://github.com/wiremock/WireMock.Net/issues/1390) - Unable to build WireMockContainerBuilder with custom image [feature]
|
||||||
|
|
||||||
|
# 1.18.0 (09 December 2025)
|
||||||
|
- [#1388](https://github.com/wiremock/WireMock.Net/pull/1388) - Add WithBodyAsType to RequestMatcher [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|
||||||
|
# 1.17.0 (07 December 2025)
|
||||||
|
- [#1383](https://github.com/wiremock/WireMock.Net/pull/1383) - Aspire: Add WithProtoDefinition to support proto definition at server level [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#1386](https://github.com/wiremock/WireMock.Net/pull/1386) - Fix random delay in mapping json file [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#1274](https://github.com/wiremock/WireMock.Net/issues/1274) - .WithMappings to mount volume is not working for GRPC [bug]
|
||||||
|
- [#1381](https://github.com/wiremock/WireMock.Net/issues/1381) - Downstream dependencies missing after 1.16.0 release [bug]
|
||||||
|
- [#1382](https://github.com/wiremock/WireMock.Net/issues/1382) - Does Aspire support enabling HTTP/2? [feature]
|
||||||
|
- [#1385](https://github.com/wiremock/WireMock.Net/issues/1385) - Do delays and probabilities show in saved static mappings? [bug]
|
||||||
|
- [#1387](https://github.com/wiremock/WireMock.Net/issues/1387) - Tests failing with TaskCanceledException on Windows Server 2025 Build 7171 [bug]
|
||||||
|
|
||||||
# 1.16.0 (18 November 2025)
|
# 1.16.0 (18 November 2025)
|
||||||
- [#1366](https://github.com/wiremock/WireMock.Net/pull/1366) - WireMock.Net.OpenApiParser : support Examples [feature] contributed by [StefH](https://github.com/StefH)
|
- [#1366](https://github.com/wiremock/WireMock.Net/pull/1366) - WireMock.Net.OpenApiParser : support Examples [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#1375](https://github.com/wiremock/WireMock.Net/pull/1375) - Add WireMockHealthCheck in WireMock.Net.Aspire [feature] contributed by [Zguy](https://github.com/Zguy)
|
- [#1375](https://github.com/wiremock/WireMock.Net/pull/1375) - Add WireMockHealthCheck in WireMock.Net.Aspire [feature] contributed by [Zguy](https://github.com/Zguy)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Version>1.16.0</Version>
|
<VersionPrefix>1.19.0</VersionPrefix>
|
||||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||||
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
||||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
rem https://github.com/StefH/GitHubReleaseNotes
|
rem https://github.com/StefH/GitHubReleaseNotes
|
||||||
|
|
||||||
SET version=1.16.0
|
SET version=1.19.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,10 +1,6 @@
|
|||||||
# 1.16.0 (18 November 2025)
|
# 1.19.0 (12 December 2025)
|
||||||
- #1366 WireMock.Net.OpenApiParser : support Examples [feature]
|
- #1391 Update WireMockContainerBuilder (WithImage and WithCustomImage) [feature]
|
||||||
- #1375 Add WireMockHealthCheck in WireMock.Net.Aspire [feature]
|
- #1392 WireMockContainerBuilder: allow all docker images named wiremock [feature]
|
||||||
- #1377 Check if the path is valid when using WithPath(...) [feature]
|
- #1390 Unable to build WireMockContainerBuilder with custom image [feature]
|
||||||
- #1380 Add WireMock.Net.xUnit.v3 project [feature]
|
|
||||||
- #1364 Choosing examples from open api specification for responses. [feature]
|
|
||||||
- #1376 AdminApiMappingBuilder `WithPath` should add the starting `/` if missing [feature]
|
|
||||||
- #1379 xUnit v3 [feature]
|
|
||||||
|
|
||||||
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
|
||||||
@@ -33,7 +33,7 @@ A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) w
|
|||||||
| **Issues** | [](https://github.com/wiremock/WireMock.Net/issues) |
|
| **Issues** | [](https://github.com/wiremock/WireMock.Net/issues) |
|
||||||
| | |
|
| | |
|
||||||
| ***Quality*** | |
|
| ***Quality*** | |
|
||||||
| **Build Azure** | [](https://stef.visualstudio.com/WireMock.Net/_build/latest?definitionId=7) |
|
| **Build Azure** | [](https://stef.visualstudio.com/WireMock.Net/_build/latest?definitionId=61) |
|
||||||
| **Quality** | [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net) [](https://www.codefactor.io/repository/github/wiremock/wiremock.net) |
|
| **Quality** | [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net) [](https://www.codefactor.io/repository/github/wiremock/wiremock.net) |
|
||||||
| **Sonar Bugs** | [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=BUG) [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=CODE_SMELL) |
|
| **Sonar Bugs** | [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=BUG) [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=CODE_SMELL) |
|
||||||
| **Coverage** | [](https://sonarcloud.io/component_measures?id=WireMock-Net_WireMock.Net&metric=coverage) [](https://codecov.io/gh/wiremock/WireMock.Net)|
|
| **Coverage** | [](https://sonarcloud.io/component_measures?id=WireMock-Net_WireMock.Net&metric=coverage) [](https://codecov.io/gh/wiremock/WireMock.Net)|
|
||||||
|
|||||||
@@ -144,6 +144,10 @@ jobs:
|
|||||||
vmImage: 'windows-2022'
|
vmImage: 'windows-2022'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
- script: |
|
||||||
|
echo "BuildId = $(buildId)"
|
||||||
|
displayName: 'Print buildId'
|
||||||
|
|
||||||
- task: UseDotNet@2
|
- task: UseDotNet@2
|
||||||
displayName: Use .NET 8.0
|
displayName: Use .NET 8.0
|
||||||
inputs:
|
inputs:
|
||||||
|
|||||||
@@ -21,4 +21,13 @@
|
|||||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.2.0" />
|
<PackageReference Include="Aspire.Hosting.AppHost" Version="9.2.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="__admin\mappings\*.proto">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="__admin\mappings\*.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -4,12 +4,25 @@ var builder = DistributedApplication.CreateBuilder(args);
|
|||||||
|
|
||||||
// IResourceBuilder<ProjectResource> apiService = builder.AddProject<Projects.AspireApp1_ApiService>("apiservice");
|
// IResourceBuilder<ProjectResource> apiService = builder.AddProject<Projects.AspireApp1_ApiService>("apiservice");
|
||||||
|
|
||||||
var mappingsPath = Path.Combine(Directory.GetCurrentDirectory(), "WireMockMappings");
|
var mappingsPath = Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings");
|
||||||
|
|
||||||
IResourceBuilder<WireMockServerResource> apiService = builder
|
//IResourceBuilder<WireMockServerResource> apiService1 = builder
|
||||||
.AddWireMock("apiservice", WireMockServerArguments.DefaultPort)
|
// //.AddWireMock("apiservice", WireMockServerArguments.DefaultPort)
|
||||||
|
// .AddWireMock("apiservice1", "http://*:8081", "grpc://*:9091")
|
||||||
|
// .AsHttp2Service()
|
||||||
|
// .WithMappingsPath(mappingsPath)
|
||||||
|
// .WithReadStaticMappings()
|
||||||
|
// .WithWatchStaticMappings()
|
||||||
|
// .WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync);
|
||||||
|
|
||||||
|
IResourceBuilder<WireMockServerResource> apiService2 = builder
|
||||||
|
.AddWireMock("apiservice", async args =>
|
||||||
|
{
|
||||||
|
args.WithAdditionalUrls("http://*:8081", "grpc://*:9093");
|
||||||
|
args.WithProtoDefinition("my-greeter", await File.ReadAllTextAsync(Path.Combine(mappingsPath, "greet.proto")));
|
||||||
|
})
|
||||||
|
.AsHttp2Service()
|
||||||
.WithMappingsPath(mappingsPath)
|
.WithMappingsPath(mappingsPath)
|
||||||
.WithReadStaticMappings()
|
|
||||||
.WithWatchStaticMappings()
|
.WithWatchStaticMappings()
|
||||||
.WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync);
|
.WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync);
|
||||||
|
|
||||||
@@ -45,7 +58,7 @@ IResourceBuilder<WireMockServerResource> apiService = builder
|
|||||||
|
|
||||||
builder.AddProject<Projects.AspireApp1_Web>("webfrontend")
|
builder.AddProject<Projects.AspireApp1_Web>("webfrontend")
|
||||||
.WithExternalHttpEndpoints()
|
.WithExternalHttpEndpoints()
|
||||||
.WithReference(apiService)
|
.WithReference(apiService2)
|
||||||
.WaitFor(apiService);
|
.WaitFor(apiService2);
|
||||||
|
|
||||||
builder.Build().Run();
|
await builder.Build().RunAsync();
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
syntax = "proto3";
|
||||||
|
|
||||||
|
package greet;
|
||||||
|
|
||||||
|
service Greeter {
|
||||||
|
rpc SayHello (HelloRequest) returns (HelloReply);
|
||||||
|
}
|
||||||
|
|
||||||
|
message HelloRequest {
|
||||||
|
string name = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
message HelloReply {
|
||||||
|
string message = 1;
|
||||||
|
enum PhoneType {
|
||||||
|
none = 0;
|
||||||
|
mobile = 1;
|
||||||
|
home = 2;
|
||||||
|
}
|
||||||
|
PhoneType phoneType = 2;
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
{
|
||||||
|
"Guid": "351f0240-bba0-4bcb-93c6-1feba0fe0004",
|
||||||
|
"Title": "ProtoBuf Mapping 4",
|
||||||
|
"Request": {
|
||||||
|
"Path": {
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "WildcardMatcher",
|
||||||
|
"Pattern": "/greet.Greeter/SayHello",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Methods": [
|
||||||
|
"POST"
|
||||||
|
],
|
||||||
|
"Body": {
|
||||||
|
"Matcher": {
|
||||||
|
"Name": "ProtoBufMatcher",
|
||||||
|
"ProtoBufMessageType": "greet.HelloRequest"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"BodyAsJson": {
|
||||||
|
"message": "hello {{request.BodyAsJson.name}} {{request.method}}"
|
||||||
|
},
|
||||||
|
"UseTransformer": true,
|
||||||
|
"TransformerType": "Handlebars",
|
||||||
|
"TransformerReplaceNodeOptions": "EvaluateAndTryToConvert",
|
||||||
|
"Headers": {
|
||||||
|
"Content-Type": "application/grpc"
|
||||||
|
},
|
||||||
|
"TrailingHeaders": {
|
||||||
|
"grpc-status": "0"
|
||||||
|
},
|
||||||
|
"ProtoBufMessageType": "greet.HelloReply"
|
||||||
|
},
|
||||||
|
"ProtoDefinition": "my-greeter"
|
||||||
|
}
|
||||||
@@ -24,4 +24,13 @@ public class StatusModel
|
|||||||
/// The error message.
|
/// The error message.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Error { get; set; }
|
public string? Error { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Returns a string that represents the current status model, including its unique identifier, status, and error information.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A string containing the values of the Guid, Status, and Error properties formatted for display.</returns>
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"StatusModel [Guid={Guid}, Status={Status}, Error={Error}]";
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -30,7 +30,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\WireMock.Net.Minimal\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" />
|
<Compile Include="..\WireMock.Net.Minimal\Util\EnhancedFileSystemWatcher.cs" Link="Util\EnhancedFileSystemWatcher.cs" />
|
||||||
|
<Compile Include="..\WireMock.Net.Minimal\Constants\WireMockConstants.cs" Link="Constants\WireMockConstants.cs" />
|
||||||
|
<Compile Include="..\WireMock.Net.Shared\Constants\RegexConstants.cs" Link="Constants\RegexConstants.cs" />
|
||||||
|
<Compile Include="..\WireMock.Net.Minimal\Util\PortUtils.cs" Link="Util\PortUtils.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
|
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
|
||||||
|
|||||||
@@ -4,7 +4,9 @@ namespace WireMock.Net.Aspire;
|
|||||||
|
|
||||||
internal enum WireMockMappingState
|
internal enum WireMockMappingState
|
||||||
{
|
{
|
||||||
NoMappings,
|
NoMappings = 0,
|
||||||
NotSubmitted,
|
|
||||||
Submitted,
|
NotSubmitted = 1,
|
||||||
|
|
||||||
|
Submitted = 2
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
|
using Stef.Validation;
|
||||||
using WireMock.Client.Builders;
|
using WireMock.Client.Builders;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace Aspire.Hosting;
|
namespace Aspire.Hosting;
|
||||||
@@ -21,10 +23,15 @@ public class WireMockServerArguments
|
|||||||
private const string DefaultLogger = "WireMockConsoleLogger";
|
private const string DefaultLogger = "WireMockConsoleLogger";
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The HTTP port where WireMock.Net is listening.
|
/// The HTTP ports where WireMock.Net is listening on.
|
||||||
/// If not defined, .NET Aspire automatically assigns a random port.
|
/// If not defined, .NET Aspire automatically assigns a random port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? HttpPort { get; set; }
|
public List<int> HttpPorts { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Additional Urls on which WireMock listens.
|
||||||
|
/// </summary>
|
||||||
|
public List<string> AdditionalUrls { get; set; } = [];
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The admin username.
|
/// The admin username.
|
||||||
@@ -67,6 +74,42 @@ public class WireMockServerArguments
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<AdminApiMappingBuilder, CancellationToken, Task>? ApiMappingBuilder { get; set; }
|
public Func<AdminApiMappingBuilder, CancellationToken, Task>? ApiMappingBuilder { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Grpc ProtoDefinitions.
|
||||||
|
/// </summary>
|
||||||
|
public Dictionary<string, string[]> ProtoDefinitions { get; set; } = [];
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add an additional Urls on which WireMock should listen.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="additionalUrls">The additional urls which the WireMock Server should listen on.</param>
|
||||||
|
public void WithAdditionalUrls(params string[] additionalUrls)
|
||||||
|
{
|
||||||
|
foreach (var url in additionalUrls)
|
||||||
|
{
|
||||||
|
if (!PortUtils.TryExtract(Guard.NotNullOrEmpty(url), out _, out _, out _, out _, out var port))
|
||||||
|
{
|
||||||
|
throw new ArgumentException($"The URL '{url}' is not valid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
AdditionalUrls.Add(Guard.NotNullOrWhiteSpace(url));
|
||||||
|
HttpPorts.Add(port);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a Grpc ProtoDefinition at server-level.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">Unique identifier for the ProtoDefinition.</param>
|
||||||
|
/// <param name="protoDefinitions">The ProtoDefinition as text.</param>
|
||||||
|
public void WithProtoDefinition(string id, params string[] protoDefinitions)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrWhiteSpace(id);
|
||||||
|
Guard.NotNullOrEmpty(protoDefinitions);
|
||||||
|
|
||||||
|
ProtoDefinitions[id] = protoDefinitions;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Converts the current instance's properties to an array of command-line arguments for starting the WireMock.Net server.
|
/// Converts the current instance's properties to an array of command-line arguments for starting the WireMock.Net server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -95,6 +138,11 @@ public class WireMockServerArguments
|
|||||||
Add(args, "--WatchStaticMappingsInSubdirectories", "true");
|
Add(args, "--WatchStaticMappingsInSubdirectories", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (AdditionalUrls.Count > 0)
|
||||||
|
{
|
||||||
|
Add(args, "--Urls", $"http://*:{HttpContainerPort} {string.Join(' ', AdditionalUrls)}");
|
||||||
|
}
|
||||||
|
|
||||||
return args
|
return args
|
||||||
.SelectMany(k => new[] { k.Key, k.Value })
|
.SelectMany(k => new[] { k.Key, k.Value })
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ using Microsoft.Extensions.Diagnostics.HealthChecks;
|
|||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Client.Builders;
|
using WireMock.Client.Builders;
|
||||||
using WireMock.Net.Aspire;
|
using WireMock.Net.Aspire;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace Aspire.Hosting;
|
namespace Aspire.Hosting;
|
||||||
@@ -34,9 +35,31 @@ public static class WireMockServerBuilderExtensions
|
|||||||
Guard.NotNullOrWhiteSpace(name);
|
Guard.NotNullOrWhiteSpace(name);
|
||||||
Guard.Condition(port, p => p is null or > 0 and <= ushort.MaxValue);
|
Guard.Condition(port, p => p is null or > 0 and <= ushort.MaxValue);
|
||||||
|
|
||||||
return builder.AddWireMock(name, callback =>
|
return builder.AddWireMock(name, serverArguments =>
|
||||||
{
|
{
|
||||||
callback.HttpPort = port;
|
if (port != null)
|
||||||
|
{
|
||||||
|
serverArguments.HttpPorts = [port.Value];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds a WireMock.Net Server resource to the application model.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The <see cref="IDistributedApplicationBuilder"/>.</param>
|
||||||
|
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
|
||||||
|
/// <param name="additionalUrls">The additional urls which the WireMock Server should listen on.</param>
|
||||||
|
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||||
|
public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, params string[] additionalUrls)
|
||||||
|
{
|
||||||
|
Guard.NotNull(builder);
|
||||||
|
Guard.NotNullOrWhiteSpace(name);
|
||||||
|
Guard.NotNull(additionalUrls);
|
||||||
|
|
||||||
|
return builder.AddWireMock(name, serverArguments =>
|
||||||
|
{
|
||||||
|
serverArguments.WithAdditionalUrls(additionalUrls);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -67,10 +90,37 @@ public static class WireMockServerBuilderExtensions
|
|||||||
.AddResource(wireMockContainerResource)
|
.AddResource(wireMockContainerResource)
|
||||||
.WithImage(DefaultLinuxImage)
|
.WithImage(DefaultLinuxImage)
|
||||||
.WithEnvironment(ctx => ctx.EnvironmentVariables.Add("DOTNET_USE_POLLING_FILE_WATCHER", "1")) // https://khalidabuhakmeh.com/aspnet-docker-gotchas-and-workarounds#configuration-reloads-and-filesystemwatcher
|
.WithEnvironment(ctx => ctx.EnvironmentVariables.Add("DOTNET_USE_POLLING_FILE_WATCHER", "1")) // https://khalidabuhakmeh.com/aspnet-docker-gotchas-and-workarounds#configuration-reloads-and-filesystemwatcher
|
||||||
.WithHttpEndpoint(port: arguments.HttpPort, targetPort: WireMockServerArguments.HttpContainerPort)
|
|
||||||
.WithHealthCheck(healthCheckKey)
|
.WithHealthCheck(healthCheckKey)
|
||||||
.WithWireMockInspectorCommand();
|
.WithWireMockInspectorCommand();
|
||||||
|
|
||||||
|
if (arguments.HttpPorts.Count == 0)
|
||||||
|
{
|
||||||
|
resourceBuilder = resourceBuilder.WithHttpEndpoint(port: null, targetPort: WireMockServerArguments.HttpContainerPort);
|
||||||
|
}
|
||||||
|
else if (arguments.HttpPorts.Count == 1)
|
||||||
|
{
|
||||||
|
resourceBuilder = resourceBuilder.WithHttpEndpoint(port: arguments.HttpPorts[0], targetPort: WireMockServerArguments.HttpContainerPort);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Required for the default admin endpoint and health checks
|
||||||
|
resourceBuilder = resourceBuilder.WithHttpEndpoint(port: null, targetPort: WireMockServerArguments.HttpContainerPort);
|
||||||
|
|
||||||
|
var anyIsHttp2 = false;
|
||||||
|
foreach (var url in arguments.AdditionalUrls)
|
||||||
|
{
|
||||||
|
PortUtils.TryExtract(url, out _, out var isHttp2, out var scheme, out _, out var httpPort);
|
||||||
|
anyIsHttp2 |= isHttp2;
|
||||||
|
|
||||||
|
resourceBuilder = resourceBuilder.WithEndpoint(port: httpPort, targetPort: httpPort, scheme: scheme, name: $"{scheme}-{httpPort}");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (anyIsHttp2)
|
||||||
|
{
|
||||||
|
resourceBuilder = resourceBuilder.AsHttp2Service();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(arguments.MappingsPath))
|
if (!string.IsNullOrEmpty(arguments.MappingsPath))
|
||||||
{
|
{
|
||||||
resourceBuilder = resourceBuilder.WithBindMount(arguments.MappingsPath, DefaultLinuxMappingsPath);
|
resourceBuilder = resourceBuilder.WithBindMount(arguments.MappingsPath, DefaultLinuxMappingsPath);
|
||||||
@@ -84,6 +134,9 @@ public static class WireMockServerBuilderExtensions
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// Always add the lifecycle hook to support dynamic mappings and proto definitions
|
||||||
|
resourceBuilder.ApplicationBuilder.Services.TryAddLifecycleHook<WireMockServerLifecycleHook>();
|
||||||
|
|
||||||
return resourceBuilder;
|
return resourceBuilder;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,7 +147,10 @@ public static class WireMockServerBuilderExtensions
|
|||||||
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
|
/// <param name="name">The name of the resource. This name will be used as the connection string name when referenced in a dependency.</param>
|
||||||
/// <param name="callback">A callback that allows for setting the <see cref="WireMockServerArguments"/>.</param>
|
/// <param name="callback">A callback that allows for setting the <see cref="WireMockServerArguments"/>.</param>
|
||||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||||
public static IResourceBuilder<WireMockServerResource> AddWireMock(this IDistributedApplicationBuilder builder, string name, Action<WireMockServerArguments> callback)
|
public static IResourceBuilder<WireMockServerResource> AddWireMock(
|
||||||
|
this IDistributedApplicationBuilder builder,
|
||||||
|
string name,
|
||||||
|
Action<WireMockServerArguments> callback)
|
||||||
{
|
{
|
||||||
Guard.NotNull(builder);
|
Guard.NotNull(builder);
|
||||||
Guard.NotNullOrWhiteSpace(name);
|
Guard.NotNullOrWhiteSpace(name);
|
||||||
@@ -165,7 +221,7 @@ public static class WireMockServerBuilderExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
||||||
/// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param>
|
/// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param>
|
||||||
/// <returns></returns>
|
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||||
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, Task> configure)
|
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, Task> configure)
|
||||||
{
|
{
|
||||||
return wiremock.WithApiMappingBuilder((adminApiMappingBuilder, _) => configure.Invoke(adminApiMappingBuilder));
|
return wiremock.WithApiMappingBuilder((adminApiMappingBuilder, _) => configure.Invoke(adminApiMappingBuilder));
|
||||||
@@ -176,18 +232,31 @@ public static class WireMockServerBuilderExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
||||||
/// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param>
|
/// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param>
|
||||||
/// <returns></returns>
|
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||||
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, CancellationToken, Task> configure)
|
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, CancellationToken, Task> configure)
|
||||||
{
|
{
|
||||||
Guard.NotNull(wiremock);
|
Guard.NotNull(wiremock);
|
||||||
|
|
||||||
wiremock.ApplicationBuilder.Services.TryAddLifecycleHook<WireMockServerLifecycleHook>();
|
|
||||||
wiremock.Resource.Arguments.ApiMappingBuilder = configure;
|
wiremock.Resource.Arguments.ApiMappingBuilder = configure;
|
||||||
wiremock.Resource.ApiMappingState = WireMockMappingState.NotSubmitted;
|
wiremock.Resource.ApiMappingState = WireMockMappingState.NotSubmitted;
|
||||||
|
|
||||||
return wiremock;
|
return wiremock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a Grpc ProtoDefinition at server-level.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
||||||
|
/// <param name="id">Unique identifier for the ProtoDefinition.</param>
|
||||||
|
/// <param name="protoDefinitions">The ProtoDefinition as text.</param>
|
||||||
|
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||||
|
public static IResourceBuilder<WireMockServerResource> WithProtoDefinition(this IResourceBuilder<WireMockServerResource> wiremock, string id, params string[] protoDefinitions)
|
||||||
|
{
|
||||||
|
Guard.NotNull(wiremock).Resource.Arguments.WithProtoDefinition(id, protoDefinitions);
|
||||||
|
|
||||||
|
return wiremock;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Enables the WireMockInspect, a cross-platform UI app that facilitates WireMock troubleshooting.
|
/// Enables the WireMockInspect, a cross-platform UI app that facilitates WireMock troubleshooting.
|
||||||
/// This requires installation of the WireMockInspector tool.
|
/// This requires installation of the WireMockInspector tool.
|
||||||
@@ -195,11 +264,11 @@ public static class WireMockServerBuilderExtensions
|
|||||||
/// dotnet tool install WireMockInspector --global --no-cache --ignore-failed-sources
|
/// dotnet tool install WireMockInspector --global --no-cache --ignore-failed-sources
|
||||||
/// </code>
|
/// </code>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="builder">The <see cref="IResourceBuilder{WireMockNetResource}"/>.</param>
|
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockNetResource}"/>.</param>
|
||||||
/// <returns></returns>
|
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||||
public static IResourceBuilder<WireMockServerResource> WithWireMockInspectorCommand(this IResourceBuilder<WireMockServerResource> builder)
|
public static IResourceBuilder<WireMockServerResource> WithWireMockInspectorCommand(this IResourceBuilder<WireMockServerResource> wiremock)
|
||||||
{
|
{
|
||||||
Guard.NotNull(builder);
|
Guard.NotNull(wiremock);
|
||||||
|
|
||||||
CommandOptions commandOptions = new()
|
CommandOptions commandOptions = new()
|
||||||
{
|
{
|
||||||
@@ -209,13 +278,13 @@ public static class WireMockServerBuilderExtensions
|
|||||||
IconVariant = IconVariant.Filled
|
IconVariant = IconVariant.Filled
|
||||||
};
|
};
|
||||||
|
|
||||||
builder.WithCommand(
|
wiremock.WithCommand(
|
||||||
name: "wiremock-inspector",
|
name: "wiremock-inspector",
|
||||||
displayName: "WireMock Inspector",
|
displayName: "WireMock Inspector",
|
||||||
executeCommand: _ => OnRunOpenInspectorCommandAsync(builder),
|
executeCommand: _ => OnRunOpenInspectorCommandAsync(wiremock),
|
||||||
commandOptions: commandOptions);
|
commandOptions: commandOptions);
|
||||||
|
|
||||||
return builder;
|
return wiremock;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Task<ExecuteCommandResult> OnRunOpenInspectorCommandAsync(IResourceBuilder<WireMockServerResource> builder)
|
private static Task<ExecuteCommandResult> OnRunOpenInspectorCommandAsync(IResourceBuilder<WireMockServerResource> builder)
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System.Diagnostics;
|
||||||
using Aspire.Hosting.ApplicationModel;
|
using Aspire.Hosting.ApplicationModel;
|
||||||
using Aspire.Hosting.Lifecycle;
|
using Aspire.Hosting.Lifecycle;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
@@ -28,10 +29,12 @@ internal class WireMockServerLifecycleHook(ILoggerFactory loggerFactory) : IDist
|
|||||||
wireMockServerResource.SetLogger(loggerFactory.CreateLogger<WireMockServerResource>());
|
wireMockServerResource.SetLogger(loggerFactory.CreateLogger<WireMockServerResource>());
|
||||||
|
|
||||||
var endpoint = wireMockServerResource.GetEndpoint();
|
var endpoint = wireMockServerResource.GetEndpoint();
|
||||||
System.Diagnostics.Debug.Assert(endpoint.IsAllocated);
|
Debug.Assert(endpoint.IsAllocated);
|
||||||
|
|
||||||
await wireMockServerResource.WaitForHealthAsync(_linkedCts.Token);
|
await wireMockServerResource.WaitForHealthAsync(_linkedCts.Token);
|
||||||
|
|
||||||
|
await wireMockServerResource.CallAddProtoDefinitionsAsync(_linkedCts.Token);
|
||||||
|
|
||||||
await wireMockServerResource.CallApiMappingBuilderActionAsync(_linkedCts.Token);
|
await wireMockServerResource.CallApiMappingBuilderActionAsync(_linkedCts.Token);
|
||||||
|
|
||||||
wireMockServerResource.StartWatchingStaticMappings(_linkedCts.Token);
|
wireMockServerResource.StartWatchingStaticMappings(_linkedCts.Token);
|
||||||
|
|||||||
@@ -70,6 +70,34 @@ public class WireMockServerResource : ContainerResource, IResourceWithServiceDis
|
|||||||
ApiMappingState = WireMockMappingState.Submitted;
|
ApiMappingState = WireMockMappingState.Submitted;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal async Task CallAddProtoDefinitionsAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_logger?.LogInformation("Calling AdminApi to add GRPC ProtoDefinition at server level to WireMock.Net");
|
||||||
|
|
||||||
|
foreach (var (id, protoDefinitions) in Arguments.ProtoDefinitions)
|
||||||
|
{
|
||||||
|
_logger?.LogInformation("Adding ProtoDefinition {Id}", id);
|
||||||
|
foreach (var protoDefinition in protoDefinitions)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var status = await AdminApi.Value.AddProtoDefinitionAsync(id, protoDefinition, cancellationToken);
|
||||||
|
_logger?.LogInformation("ProtoDefinition '{Id}' added with status: {Status}.", id, status.Status);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger?.LogWarning(ex, "Error adding ProtoDefinition '{Id}'.", id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Force a reload of static mappings when ProtoDefinitions are added at server-level to fix #1382
|
||||||
|
if (Arguments.ProtoDefinitions.Count > 0)
|
||||||
|
{
|
||||||
|
await ReloadStaticMappingsAsync(default);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
internal void StartWatchingStaticMappings(CancellationToken cancellationToken)
|
internal void StartWatchingStaticMappings(CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
if (!Arguments.WatchStaticMappings || string.IsNullOrEmpty(Arguments.MappingsPath))
|
if (!Arguments.WatchStaticMappings || string.IsNullOrEmpty(Arguments.MappingsPath))
|
||||||
@@ -113,10 +141,17 @@ public class WireMockServerResource : ContainerResource, IResourceWithServiceDis
|
|||||||
|
|
||||||
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
||||||
{
|
{
|
||||||
_logger?.LogInformation("MappingFile created, changed or deleted: '{0}'. Triggering ReloadStaticMappings.", args.FullPath);
|
_logger?.LogInformation("MappingFile created, changed or deleted: '{FullPath}'. Triggering ReloadStaticMappings.", args.FullPath);
|
||||||
|
|
||||||
|
await ReloadStaticMappingsAsync(default);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ReloadStaticMappingsAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await AdminApi.Value.ReloadStaticMappingsAsync();
|
var status = await AdminApi.Value.ReloadStaticMappingsAsync(cancellationToken);
|
||||||
|
_logger?.LogInformation("ReloadStaticMappings called with status: {Status}.", status);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Stef.Validation;
|
||||||
|
|
||||||
|
namespace WireMock.Matchers.Request;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The request body matcher.
|
||||||
|
/// </summary>
|
||||||
|
public class RequestMessageBodyMatcher<T> : IRequestMatcher
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The body data function for type T
|
||||||
|
/// </summary>
|
||||||
|
public Func<T?, bool>? Func { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="MatchOperator"/>
|
||||||
|
/// </summary>
|
||||||
|
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="func">The function.</param>
|
||||||
|
public RequestMessageBodyMatcher(Func<T?, bool> func)
|
||||||
|
{
|
||||||
|
Func = Guard.NotNull(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||||
|
{
|
||||||
|
var (score, exception) = CalculateMatchScore(requestMessage).Expand();
|
||||||
|
return requestMatchResult.AddScore(GetType(), score, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MatchResult CalculateMatchScore(IRequestMessage requestMessage)
|
||||||
|
{
|
||||||
|
if (Func != null)
|
||||||
|
{
|
||||||
|
if (requestMessage.BodyData?.BodyAsJson is JObject jsonObject)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var bodyAsT = jsonObject.ToObject<T>();
|
||||||
|
return MatchScores.ToScore(Func(bodyAsT));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new MatchResult(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,13 +34,6 @@ public partial class Request
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
|
||||||
{
|
|
||||||
var matcher = body as IMatcher ?? new JsonMatcher(matchBehaviour, body);
|
|
||||||
return WithBody([matcher]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder WithBody(IMatcher matcher)
|
public IRequestBuilder WithBody(IMatcher matcher)
|
||||||
{
|
{
|
||||||
@@ -98,4 +91,20 @@ public partial class Request
|
|||||||
_requestMatchers.Add(new RequestMessageBodyMatcher(Guard.NotNull(func)));
|
_requestMatchers.Add(new RequestMessageBodyMatcher(Guard.NotNull(func)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
|
{
|
||||||
|
var matcher = body as IMatcher ?? new JsonMatcher(matchBehaviour, body);
|
||||||
|
return WithBody([matcher]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IRequestBuilder WithBodyAsType<T>(Func<T?, bool> func)
|
||||||
|
{
|
||||||
|
Guard.NotNull(func);
|
||||||
|
|
||||||
|
_requestMatchers.Add(new RequestMessageBodyMatcher<T>(func));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
|
|||||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||||
public static IRequestBuilder Create()
|
public static IRequestBuilder Create()
|
||||||
{
|
{
|
||||||
return new Request(new List<IRequestMatcher>());
|
return new Request([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -226,14 +226,14 @@ internal class MappingConverter(MatcherMapper mapper)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (response.Delay is { })
|
if (response is { MinimumDelayMilliseconds: > 0, MaximumDelayMilliseconds: > 0 })
|
||||||
{
|
|
||||||
sb.AppendLine($" .WithDelay({response.Delay.Value.TotalMilliseconds})");
|
|
||||||
}
|
|
||||||
else if (response is { MinimumDelayMilliseconds: > 0, MaximumDelayMilliseconds: > 0 })
|
|
||||||
{
|
{
|
||||||
sb.AppendLine($" .WithRandomDelay({response.MinimumDelayMilliseconds}, {response.MaximumDelayMilliseconds})");
|
sb.AppendLine($" .WithRandomDelay({response.MinimumDelayMilliseconds}, {response.MaximumDelayMilliseconds})");
|
||||||
}
|
}
|
||||||
|
else if (response.Delay is { })
|
||||||
|
{
|
||||||
|
sb.AppendLine($" .WithDelay({response.Delay.Value.TotalMilliseconds})");
|
||||||
|
}
|
||||||
|
|
||||||
if (response.UseTransformer)
|
if (response.UseTransformer)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ internal class SimpleSettingsParser
|
|||||||
// Now also parse environment
|
// Now also parse environment
|
||||||
if (environment != null)
|
if (environment != null)
|
||||||
{
|
{
|
||||||
foreach (string key in environment.Keys)
|
foreach (var key in environment.Keys.OfType<string>())
|
||||||
{
|
{
|
||||||
if (key.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase) && environment.TryGetStringValue(key, out var value))
|
if (key.StartsWith(Prefix, StringComparison.OrdinalIgnoreCase) && environment.TryGetStringValue(key, out var value))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -153,7 +153,7 @@ public static class WireMockServerSettingsParser
|
|||||||
}
|
}
|
||||||
else if (settings.HostingScheme is null)
|
else if (settings.HostingScheme is null)
|
||||||
{
|
{
|
||||||
settings.Urls = parser.GetValues("Urls", ["http://*:9091/"]);
|
settings.Urls = parser.GetValues(nameof(WireMockServerSettings.Urls), defaultValue: ["http://*:9091/"]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -84,22 +84,22 @@ internal static class PortUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extract the isHttps, isHttp2, protocol, host and port from a URL.
|
/// Extract the isHttps, isHttp2, scheme, host and port from a URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static bool TryExtract(string url, out bool isHttps, out bool isHttp2, [NotNullWhen(true)] out string? protocol, [NotNullWhen(true)] out string? host, out int port)
|
public static bool TryExtract(string url, out bool isHttps, out bool isHttp2, [NotNullWhen(true)] out string? scheme, [NotNullWhen(true)] out string? host, out int port)
|
||||||
{
|
{
|
||||||
isHttps = false;
|
isHttps = false;
|
||||||
isHttp2 = false;
|
isHttp2 = false;
|
||||||
protocol = null;
|
scheme = null;
|
||||||
host = null;
|
host = null;
|
||||||
port = 0;
|
port = 0;
|
||||||
|
|
||||||
var match = UrlDetailsRegex.Match(url);
|
var match = UrlDetailsRegex.Match(url);
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
{
|
{
|
||||||
protocol = match.Groups["proto"].Value;
|
scheme = match.Groups["proto"].Value;
|
||||||
isHttps = protocol.StartsWith("https", StringComparison.OrdinalIgnoreCase) || protocol.StartsWith("grpcs", StringComparison.OrdinalIgnoreCase);
|
isHttps = scheme.StartsWith("https", StringComparison.OrdinalIgnoreCase) || scheme.StartsWith("grpcs", StringComparison.OrdinalIgnoreCase);
|
||||||
isHttp2 = protocol.StartsWith("grpc", StringComparison.OrdinalIgnoreCase);
|
isHttp2 = scheme.StartsWith("grpc", StringComparison.OrdinalIgnoreCase);
|
||||||
host = match.Groups["host"].Value;
|
host = match.Groups["host"].Value;
|
||||||
|
|
||||||
return int.TryParse(match.Groups["port"].Value, out port);
|
return int.TryParse(match.Groups["port"].Value, out port);
|
||||||
|
|||||||
@@ -80,6 +80,14 @@ public interface IBodyRequestBuilder : IMultiPartRequestBuilder
|
|||||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||||
IRequestBuilder WithBody(Func<object?, bool> func);
|
IRequestBuilder WithBody(Func<object?, bool> func);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WithBody: func (type)
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type.</typeparam>
|
||||||
|
/// <param name="func">The function.</param>
|
||||||
|
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||||
|
IRequestBuilder WithBodyAsType<T>(Func<T?, bool> func);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// WithBody: func (BodyData object)
|
/// WithBody: func (BodyData object)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -156,7 +156,8 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _adminApi.ReloadStaticMappingsAsync(cancellationToken);
|
var result = await _adminApi.ReloadStaticMappingsAsync(cancellationToken);
|
||||||
|
Logger.LogInformation("ReloadStaticMappings result: {Result}", result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -231,7 +232,8 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
await _adminApi!.AddProtoDefinitionAsync(kvp.Key, protoDefinition);
|
var result = await _adminApi!.AddProtoDefinitionAsync(kvp.Key, protoDefinition);
|
||||||
|
Logger.LogInformation("AddProtoDefinition '{Id}' result: {Result}", kvp.Key, result);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
@@ -239,6 +241,12 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Force a reload of static mappings when ProtoDefinitions are added at server-level to fix #1382
|
||||||
|
if (_configuration.ProtoDefinitions.Count > 0)
|
||||||
|
{
|
||||||
|
await ReloadStaticMappingsAsync();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
||||||
@@ -246,6 +254,7 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
await ReloadStaticMappingsAsync(args.FullPath);
|
await ReloadStaticMappingsAsync(args.FullPath);
|
||||||
|
Logger.LogInformation("ReloadStaticMappings triggered from file change: '{FullPath}'.", args.FullPath);
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -62,6 +62,29 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
return WithImage(OSPlatform.Windows);
|
return WithImage(OSPlatform.Windows);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a custom WireMock.Net image for which to create the container.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="image">The image name.</param>
|
||||||
|
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public new WireMockContainerBuilder WithImage(string image)
|
||||||
|
{
|
||||||
|
return WithCustomImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Sets a custom WireMock.Net image for which to create the container.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="image">The image name.</param>
|
||||||
|
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public WireMockContainerBuilder WithCustomImage(string image)
|
||||||
|
{
|
||||||
|
_imageOS ??= TestcontainersUtils.GetImageOSAsync.Value.GetAwaiter().GetResult();
|
||||||
|
return base.WithImage(image);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the admin username and password for the container (basic authentication).
|
/// Set the admin username and password for the container (basic authentication).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -112,6 +135,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
{
|
{
|
||||||
DockerResourceConfiguration.WithWatchStaticMappings(includeSubDirectories);
|
DockerResourceConfiguration.WithWatchStaticMappings(includeSubDirectories);
|
||||||
return
|
return
|
||||||
|
WithCommand("--ReadStaticMappings true").
|
||||||
WithCommand("--WatchStaticMappings true").
|
WithCommand("--WatchStaticMappings true").
|
||||||
WithCommand("--WatchStaticMappingsInSubdirectories", includeSubDirectories);
|
WithCommand("--WatchStaticMappingsInSubdirectories", includeSubDirectories);
|
||||||
}
|
}
|
||||||
@@ -129,9 +153,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
|
|
||||||
DockerResourceConfiguration.WithStaticMappingsPath(path);
|
DockerResourceConfiguration.WithStaticMappingsPath(path);
|
||||||
|
|
||||||
return
|
return WithWatchStaticMappings(includeSubDirectories);
|
||||||
WithReadStaticMappings().
|
|
||||||
WithCommand("--WatchStaticMappingsInSubdirectories", includeSubDirectories);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -208,9 +230,9 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
// In case the _imageOS is not set, determine it from the Image FullName.
|
// In case the _imageOS is not set, determine it from the Image FullName.
|
||||||
if (_imageOS == null)
|
if (_imageOS == null)
|
||||||
{
|
{
|
||||||
if (builder.DockerResourceConfiguration.Image.FullName.IndexOf("wiremock.net", StringComparison.OrdinalIgnoreCase) < 0)
|
if (builder.DockerResourceConfiguration.Image.FullName.IndexOf("wiremock", StringComparison.OrdinalIgnoreCase) < 0)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException();
|
throw new InvalidOperationException("It's only possible to use a wiremock docker image.");
|
||||||
}
|
}
|
||||||
|
|
||||||
_imageOS = builder.DockerResourceConfiguration.Image.FullName.IndexOf("windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
|
_imageOS = builder.DockerResourceConfiguration.Image.FullName.IndexOf("windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
<Description>Some extensions for xUnit (ITestOutputHelper)</Description>
|
<Description>Some extensions for xUnit (ITestOutputHelper)</Description>
|
||||||
<AssemblyTitle>WireMock.Net.xUnit.v3</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.xUnit.v3</AssemblyTitle>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<Authors>Stef Heyenrath</Authors>
|
||||||
<TargetFrameworks>net472;net8.0</TargetFrameworks>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>tdd;wiremock;test;unittest;xunit</PackageTags>
|
<PackageTags>tdd;wiremock;test;unittest;xunit</PackageTags>
|
||||||
<ProjectGuid>{4F46BD02-BEBC-4B2D-B857-4169AD222267}</ProjectGuid>
|
<ProjectGuid>{4F46BD02-BEBC-4B2D-B857-4169AD222267}</ProjectGuid>
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ public class WireMockServerArgumentsTests
|
|||||||
var args = new WireMockServerArguments();
|
var args = new WireMockServerArguments();
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
args.HttpPort.Should().BeNull();
|
args.HttpPorts.Should().BeEmpty();
|
||||||
args.AdminUsername.Should().BeNull();
|
args.AdminUsername.Should().BeNull();
|
||||||
args.AdminPassword.Should().BeNull();
|
args.AdminPassword.Should().BeNull();
|
||||||
args.ReadStaticMappings.Should().BeFalse();
|
args.ReadStaticMappings.Should().BeFalse();
|
||||||
|
|||||||
@@ -3,6 +3,7 @@
|
|||||||
using System.Net.Sockets;
|
using System.Net.Sockets;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using Moq;
|
using Moq;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Net.Aspire.Tests;
|
namespace WireMock.Net.Aspire.Tests;
|
||||||
|
|
||||||
@@ -40,7 +41,21 @@ public class WireMockServerBuilderExtensionsTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void AddWireMock()
|
public void AddWireMock_WithInvalidAdditionalUrls_ShouldThrowArgumentException()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
string[] invalidUrls = { "err" };
|
||||||
|
var builder = Mock.Of<IDistributedApplicationBuilder>();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
Action act = () => builder.AddWireMock("ValidName", invalidUrls);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
act.Should().Throw<ArgumentException>().WithMessage("The URL 'err' is not valid.");
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddWireMockWithPort()
|
||||||
{
|
{
|
||||||
// Arrange
|
// Arrange
|
||||||
var name = $"apiservice{Guid.NewGuid()}";
|
var name = $"apiservice{Guid.NewGuid()}";
|
||||||
@@ -65,7 +80,7 @@ public class WireMockServerBuilderExtensionsTests
|
|||||||
ReadStaticMappings = true,
|
ReadStaticMappings = true,
|
||||||
WatchStaticMappings = false,
|
WatchStaticMappings = false,
|
||||||
MappingsPath = null,
|
MappingsPath = null,
|
||||||
HttpPort = port
|
HttpPorts = [port]
|
||||||
});
|
});
|
||||||
wiremock.Resource.Annotations.Should().HaveCount(6);
|
wiremock.Resource.Annotations.Should().HaveCount(6);
|
||||||
|
|
||||||
@@ -90,9 +105,90 @@ public class WireMockServerBuilderExtensionsTests
|
|||||||
));
|
));
|
||||||
|
|
||||||
wiremock.Resource.Annotations.OfType<EnvironmentCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
wiremock.Resource.Annotations.OfType<EnvironmentCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||||
|
|
||||||
wiremock.Resource.Annotations.OfType<CommandLineArgsCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
wiremock.Resource.Annotations.OfType<CommandLineArgsCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||||
|
wiremock.Resource.Annotations.OfType<ResourceCommandAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void AddWireMockWithAdditionalUrls()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
var name = $"apiservice{Guid.NewGuid()}";
|
||||||
|
var freePorts = PortUtils.FindFreeTcpPorts(2).ToList();
|
||||||
|
string[] additionalUrls = { $"http://*:{freePorts[0]}", $"grpc://*:{freePorts[1]}" };
|
||||||
|
const string username = "admin";
|
||||||
|
const string password = "test";
|
||||||
|
var builder = DistributedApplication.CreateBuilder();
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var wiremock = builder
|
||||||
|
.AddWireMock(name, additionalUrls)
|
||||||
|
.WithAdminUserNameAndPassword(username, password)
|
||||||
|
.WithReadStaticMappings();
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
wiremock.Resource.Should().NotBeNull();
|
||||||
|
wiremock.Resource.Name.Should().Be(name);
|
||||||
|
wiremock.Resource.Arguments.Should().BeEquivalentTo(new WireMockServerArguments
|
||||||
|
{
|
||||||
|
AdminPassword = password,
|
||||||
|
AdminUsername = username,
|
||||||
|
ReadStaticMappings = true,
|
||||||
|
WatchStaticMappings = false,
|
||||||
|
MappingsPath = null,
|
||||||
|
HttpPorts = freePorts,
|
||||||
|
AdditionalUrls = additionalUrls.ToList()
|
||||||
|
});
|
||||||
|
wiremock.Resource.Annotations.Should().HaveCount(9);
|
||||||
|
|
||||||
|
var containerImageAnnotation = wiremock.Resource.Annotations.OfType<ContainerImageAnnotation>().FirstOrDefault();
|
||||||
|
containerImageAnnotation.Should().BeEquivalentTo(new ContainerImageAnnotation
|
||||||
|
{
|
||||||
|
Image = "sheyenrath/wiremock.net-alpine",
|
||||||
|
Registry = null,
|
||||||
|
Tag = "latest"
|
||||||
|
});
|
||||||
|
|
||||||
|
var endpointAnnotations = wiremock.Resource.Annotations.OfType<EndpointAnnotation>().ToArray();
|
||||||
|
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
|
||||||
|
));
|
||||||
|
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
|
||||||
|
));
|
||||||
|
|
||||||
|
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
|
||||||
|
));
|
||||||
|
|
||||||
|
wiremock.Resource.Annotations.OfType<EnvironmentCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||||
|
wiremock.Resource.Annotations.OfType<CommandLineArgsCallbackAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||||
wiremock.Resource.Annotations.OfType<ResourceCommandAnnotation>().FirstOrDefault().Should().NotBeNull();
|
wiremock.Resource.Annotations.OfType<ResourceCommandAnnotation>().FirstOrDefault().Should().NotBeNull();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,5 +190,92 @@
|
|||||||
BodyDestination: SameAsSource,
|
BodyDestination: SameAsSource,
|
||||||
Body: Buy milk
|
Body: Buy milk
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Guid: 98fae52e-76df-47d9-876f-2ee32e931006,
|
||||||
|
UpdatedAt: 2023-01-14 15:16:17,
|
||||||
|
Request: {
|
||||||
|
Path: {
|
||||||
|
Matchers: [
|
||||||
|
{
|
||||||
|
Name: WildcardMatcher,
|
||||||
|
Pattern: /delay,
|
||||||
|
IgnoreCase: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Methods: [
|
||||||
|
GET
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Response: {
|
||||||
|
Delay: 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Guid: 98fae52e-76df-47d9-876f-2ee32e931007,
|
||||||
|
UpdatedAt: 2023-01-14 15:16:17,
|
||||||
|
Request: {
|
||||||
|
Path: {
|
||||||
|
Matchers: [
|
||||||
|
{
|
||||||
|
Name: WildcardMatcher,
|
||||||
|
Pattern: /random-delay,
|
||||||
|
IgnoreCase: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Methods: [
|
||||||
|
GET
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Response: {
|
||||||
|
MinimumRandomDelay: 1234,
|
||||||
|
MaximumRandomDelay: 60000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Guid: 98fae52e-76df-47d9-876f-2ee32e931008,
|
||||||
|
UpdatedAt: 2023-01-14 15:16:17,
|
||||||
|
Request: {
|
||||||
|
Path: {
|
||||||
|
Matchers: [
|
||||||
|
{
|
||||||
|
Name: WildcardMatcher,
|
||||||
|
Pattern: /prob,
|
||||||
|
IgnoreCase: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Methods: [
|
||||||
|
GET
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Response: {
|
||||||
|
StatusCode: 300
|
||||||
|
},
|
||||||
|
Probability: 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Guid: 98fae52e-76df-47d9-876f-2ee32e931009,
|
||||||
|
UpdatedAt: 2023-01-14 15:16:17,
|
||||||
|
Request: {
|
||||||
|
Path: {
|
||||||
|
Matchers: [
|
||||||
|
{
|
||||||
|
Name: WildcardMatcher,
|
||||||
|
Pattern: /prob,
|
||||||
|
IgnoreCase: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Methods: [
|
||||||
|
GET
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Response: {
|
||||||
|
StatusCode: 201
|
||||||
|
},
|
||||||
|
Probability: 0.9
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -78,3 +78,45 @@ builder
|
|||||||
.WithBody("Buy milk")
|
.WithBody("Buy milk")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingMethod("GET")
|
||||||
|
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/delay", false, WireMock.Matchers.MatchOperator.Or))
|
||||||
|
)
|
||||||
|
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931006")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithDelay(1000)
|
||||||
|
);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingMethod("GET")
|
||||||
|
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/random-delay", false, WireMock.Matchers.MatchOperator.Or))
|
||||||
|
)
|
||||||
|
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931007")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithRandomDelay(1234, 60000)
|
||||||
|
);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingMethod("GET")
|
||||||
|
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/prob", false, WireMock.Matchers.MatchOperator.Or))
|
||||||
|
)
|
||||||
|
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931008")
|
||||||
|
.WithProbability(0.1)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithStatusCode(300)
|
||||||
|
);
|
||||||
|
|
||||||
|
builder
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingMethod("GET")
|
||||||
|
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/prob", false, WireMock.Matchers.MatchOperator.Or))
|
||||||
|
)
|
||||||
|
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931009")
|
||||||
|
.WithProbability(0.9)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithStatusCode(201)
|
||||||
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -78,3 +78,45 @@ server
|
|||||||
.WithBody("Buy milk")
|
.WithBody("Buy milk")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingMethod("GET")
|
||||||
|
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/delay", false, WireMock.Matchers.MatchOperator.Or))
|
||||||
|
)
|
||||||
|
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931006")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithDelay(1000)
|
||||||
|
);
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingMethod("GET")
|
||||||
|
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/random-delay", false, WireMock.Matchers.MatchOperator.Or))
|
||||||
|
)
|
||||||
|
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931007")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithRandomDelay(1234, 60000)
|
||||||
|
);
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingMethod("GET")
|
||||||
|
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/prob", false, WireMock.Matchers.MatchOperator.Or))
|
||||||
|
)
|
||||||
|
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931008")
|
||||||
|
.WithProbability(0.1)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithStatusCode(300)
|
||||||
|
);
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingMethod("GET")
|
||||||
|
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/prob", false, WireMock.Matchers.MatchOperator.Or))
|
||||||
|
)
|
||||||
|
.WithGuid("98fae52e-76df-47d9-876f-2ee32e931009")
|
||||||
|
.WithProbability(0.9)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithStatusCode(201)
|
||||||
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -186,5 +186,92 @@
|
|||||||
BodyDestination: SameAsSource,
|
BodyDestination: SameAsSource,
|
||||||
Body: Buy milk
|
Body: Buy milk
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Guid: 98fae52e-76df-47d9-876f-2ee32e931006,
|
||||||
|
UpdatedAt: 2023-01-14T15:16:17,
|
||||||
|
Request: {
|
||||||
|
Path: {
|
||||||
|
Matchers: [
|
||||||
|
{
|
||||||
|
Name: WildcardMatcher,
|
||||||
|
Pattern: /delay,
|
||||||
|
IgnoreCase: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Methods: [
|
||||||
|
GET
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Response: {
|
||||||
|
Delay: 1000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Guid: 98fae52e-76df-47d9-876f-2ee32e931007,
|
||||||
|
UpdatedAt: 2023-01-14T15:16:17,
|
||||||
|
Request: {
|
||||||
|
Path: {
|
||||||
|
Matchers: [
|
||||||
|
{
|
||||||
|
Name: WildcardMatcher,
|
||||||
|
Pattern: /random-delay,
|
||||||
|
IgnoreCase: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Methods: [
|
||||||
|
GET
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Response: {
|
||||||
|
MinimumRandomDelay: 1234,
|
||||||
|
MaximumRandomDelay: 60000
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Guid: 98fae52e-76df-47d9-876f-2ee32e931008,
|
||||||
|
UpdatedAt: 2023-01-14T15:16:17,
|
||||||
|
Request: {
|
||||||
|
Path: {
|
||||||
|
Matchers: [
|
||||||
|
{
|
||||||
|
Name: WildcardMatcher,
|
||||||
|
Pattern: /prob,
|
||||||
|
IgnoreCase: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Methods: [
|
||||||
|
GET
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Response: {
|
||||||
|
StatusCode: 300
|
||||||
|
},
|
||||||
|
Probability: 0.1
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Guid: 98fae52e-76df-47d9-876f-2ee32e931009,
|
||||||
|
UpdatedAt: 2023-01-14T15:16:17,
|
||||||
|
Request: {
|
||||||
|
Path: {
|
||||||
|
Matchers: [
|
||||||
|
{
|
||||||
|
Name: WildcardMatcher,
|
||||||
|
Pattern: /prob,
|
||||||
|
IgnoreCase: false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Methods: [
|
||||||
|
GET
|
||||||
|
]
|
||||||
|
},
|
||||||
|
Response: {
|
||||||
|
StatusCode: 201
|
||||||
|
},
|
||||||
|
Probability: 0.9
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#if !(NET452 || NET461 || NETCOREAPP3_1)
|
#if !(NET452 || NET461 || NETCOREAPP3_1)
|
||||||
using System;
|
using System;
|
||||||
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Moq;
|
using Moq;
|
||||||
using VerifyTests;
|
using VerifyTests;
|
||||||
@@ -118,6 +119,35 @@ public class MappingBuilderTests
|
|||||||
.RespondWith(Response.Create()
|
.RespondWith(Response.Create()
|
||||||
.WithBody("Buy milk"));
|
.WithBody("Buy milk"));
|
||||||
|
|
||||||
|
_sut.Given(Request.Create()
|
||||||
|
.WithPath("/delay")
|
||||||
|
.UsingGet()
|
||||||
|
).RespondWith(Response.Create()
|
||||||
|
.WithDelay(1000)
|
||||||
|
);
|
||||||
|
|
||||||
|
_sut.Given(Request.Create()
|
||||||
|
.WithPath("/random-delay")
|
||||||
|
.UsingGet()
|
||||||
|
).RespondWith(Response.Create()
|
||||||
|
.WithRandomDelay(1234)
|
||||||
|
);
|
||||||
|
|
||||||
|
_sut.Given(Request.Create()
|
||||||
|
.WithPath("/prob")
|
||||||
|
.UsingGet()
|
||||||
|
).WithProbability(0.1)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithStatusCode(HttpStatusCode.Ambiguous)
|
||||||
|
);
|
||||||
|
_sut.Given(Request.Create()
|
||||||
|
.WithPath("/prob")
|
||||||
|
.UsingGet()
|
||||||
|
).WithProbability(0.9)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithStatusCode(HttpStatusCode.Created)
|
||||||
|
);
|
||||||
|
|
||||||
_numMappings = _sut.GetMappings().Length;
|
_numMappings = _sut.GetMappings().Length;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using FluentAssertions;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using FluentAssertions;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using NFluent;
|
using NFluent;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
@@ -72,15 +73,17 @@ public class RequestBuilderWithBodyTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Request_WithBody_FuncJson()
|
public void Request_WithBody_FuncObject()
|
||||||
{
|
{
|
||||||
// Assign
|
// Assign
|
||||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody(b => b != null);
|
var requestBuilder = Request.Create()
|
||||||
|
.UsingAnyMethod()
|
||||||
|
.WithBody(b => b != null);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var body = new BodyData
|
var body = new BodyData
|
||||||
{
|
{
|
||||||
BodyAsJson = 123,
|
BodyAsJson = JObject.Parse("""{ "X": 123, "Y": "a" }"""),
|
||||||
DetectedBodyType = BodyType.Json
|
DetectedBodyType = BodyType.Json
|
||||||
};
|
};
|
||||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||||
@@ -90,6 +93,57 @@ public class RequestBuilderWithBodyTests
|
|||||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("""{ "X": 123, "Y": "a" }""", 1.0)]
|
||||||
|
[InlineData("""{ "X": 123, "Y": "b" }""", 0.0)]
|
||||||
|
public void Request_WithBodyAsType_Func(string json, double expected)
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var requestBuilder = Request.Create()
|
||||||
|
.UsingAnyMethod()
|
||||||
|
.WithBodyAsType<FuncType>(ft => ft != null && ft.X == 123 && ft.Y == "a");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var body = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsJson = JObject.Parse(json),
|
||||||
|
DetectedBodyType = BodyType.Json
|
||||||
|
};
|
||||||
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var requestMatchResult = new RequestMatchResult();
|
||||||
|
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Request_WithBodyAsType_Func_IncorrectType()
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var requestBuilder = Request.Create()
|
||||||
|
.UsingAnyMethod()
|
||||||
|
.WithBodyAsType<Version>(ft => ft != null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var body = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsJson = JObject.Parse("""{ "X": 123, "Y": "a" }"""),
|
||||||
|
DetectedBodyType = BodyType.Json
|
||||||
|
};
|
||||||
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var requestMatchResult = new RequestMatchResult();
|
||||||
|
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FuncType
|
||||||
|
{
|
||||||
|
public int X { get; set; } = 42;
|
||||||
|
|
||||||
|
public string Y { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Request_WithBody_FuncFormUrlEncoded()
|
public void Request_WithBody_FuncFormUrlEncoded()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ public partial class TestcontainersTests
|
|||||||
var grpcPort = wireMockContainer.GetMappedPublicPort(9090);
|
var grpcPort = wireMockContainer.GetMappedPublicPort(9090);
|
||||||
grpcPort.Should().BeGreaterThan(0);
|
grpcPort.Should().BeGreaterThan(0);
|
||||||
|
|
||||||
var grpcUrl = wireMockContainer.GetMappedPublicUrl(80);
|
var grpcUrl = wireMockContainer.GetMappedPublicUrl(9090);
|
||||||
grpcUrl.Should().StartWith("http://");
|
grpcUrl.Should().StartWith("http://");
|
||||||
|
|
||||||
var adminClient = wireMockContainer.CreateWireMockAdminClient();
|
var adminClient = wireMockContainer.CreateWireMockAdminClient();
|
||||||
@@ -149,6 +149,18 @@ public partial class TestcontainersTests
|
|||||||
await StopAsync(wireMockContainer);
|
await StopAsync(wireMockContainer);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionAtServerLevel_UsingGrpcGeneratedClient_AndWithWatchStaticMappings()
|
||||||
|
{
|
||||||
|
var wireMockContainer = await Given_WireMockContainerWithProtoDefinitionAtServerLevelWithWatchStaticMappingsIsStartedForHttpAndGrpcAsync();
|
||||||
|
|
||||||
|
var reply = await When_GrpcClient_Calls_SayHelloAsync(wireMockContainer);
|
||||||
|
|
||||||
|
Then_ReplyMessage_Should_BeCorrect(reply);
|
||||||
|
|
||||||
|
await StopAsync(wireMockContainer);
|
||||||
|
}
|
||||||
|
|
||||||
private static async Task<WireMockContainer> Given_WireMockContainerIsStartedForHttpAndGrpcAsync()
|
private static async Task<WireMockContainer> Given_WireMockContainerIsStartedForHttpAndGrpcAsync()
|
||||||
{
|
{
|
||||||
var wireMockContainer = new WireMockContainerBuilder()
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
@@ -172,6 +184,19 @@ public partial class TestcontainersTests
|
|||||||
return wireMockContainer;
|
return wireMockContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static async Task<WireMockContainer> Given_WireMockContainerWithProtoDefinitionAtServerLevelWithWatchStaticMappingsIsStartedForHttpAndGrpcAsync()
|
||||||
|
{
|
||||||
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.AddUrl("grpc://*:9090")
|
||||||
|
.AddProtoDefinition("my-greeter", ReadFile("greet.proto"))
|
||||||
|
.WithMappings(Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings"))
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
await wireMockContainer.StartAsync();
|
||||||
|
|
||||||
|
return wireMockContainer;
|
||||||
|
}
|
||||||
|
|
||||||
private static async Task Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(WireMockContainer wireMockContainer, string filename)
|
private static async Task Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(WireMockContainer wireMockContainer, string filename)
|
||||||
{
|
{
|
||||||
var mappingsJson = ReadFile(filename);
|
var mappingsJson = ReadFile(filename);
|
||||||
@@ -180,6 +205,8 @@ public partial class TestcontainersTests
|
|||||||
|
|
||||||
var result = await httpClient.PostAsync("/__admin/mappings", new StringContent(mappingsJson, Encoding.UTF8, WireMockConstants.ContentTypeJson));
|
var result = await httpClient.PostAsync("/__admin/mappings", new StringContent(mappingsJson, Encoding.UTF8, WireMockConstants.ContentTypeJson));
|
||||||
result.EnsureSuccessStatusCode();
|
result.EnsureSuccessStatusCode();
|
||||||
|
|
||||||
|
await Task.Delay(1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task<HelloReply> When_GrpcClient_Calls_SayHelloAsync(WireMockContainer wireMockContainer)
|
private static async Task<HelloReply> When_GrpcClient_Calls_SayHelloAsync(WireMockContainer wireMockContainer)
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ public partial class TestcontainersTests(ITestOutputHelper testOutputHelper)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
wireMockContainerBuilder = wireMockContainerBuilder.WithImage("sheyenrath/wiremock.net");
|
wireMockContainerBuilder = wireMockContainerBuilder.WithImage("sheyenrath/wiremock.net-alpine");
|
||||||
}
|
}
|
||||||
|
|
||||||
var wireMockContainer = wireMockContainerBuilder.Build();
|
var wireMockContainer = wireMockContainerBuilder.Build();
|
||||||
|
|||||||
@@ -15,13 +15,13 @@ public class PortUtilsTests
|
|||||||
var url = "test";
|
var url = "test";
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var proto, out var host, out var port);
|
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var scheme, out var host, out var port);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.Should().BeFalse();
|
result.Should().BeFalse();
|
||||||
isHttps.Should().BeFalse();
|
isHttps.Should().BeFalse();
|
||||||
isGrpc.Should().BeFalse();
|
isGrpc.Should().BeFalse();
|
||||||
proto.Should().BeNull();
|
scheme.Should().BeNull();
|
||||||
host.Should().BeNull();
|
host.Should().BeNull();
|
||||||
port.Should().Be(default(int));
|
port.Should().Be(default(int));
|
||||||
}
|
}
|
||||||
@@ -33,13 +33,13 @@ public class PortUtilsTests
|
|||||||
var url = "http://0.0.0.0";
|
var url = "http://0.0.0.0";
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var proto, out var host, out var port);
|
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var scheme, out var host, out var port);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.Should().BeFalse();
|
result.Should().BeFalse();
|
||||||
isHttps.Should().BeFalse();
|
isHttps.Should().BeFalse();
|
||||||
isGrpc.Should().BeFalse();
|
isGrpc.Should().BeFalse();
|
||||||
proto.Should().BeNull();
|
scheme.Should().BeNull();
|
||||||
host.Should().BeNull();
|
host.Should().BeNull();
|
||||||
port.Should().Be(default(int));
|
port.Should().Be(default(int));
|
||||||
}
|
}
|
||||||
@@ -51,13 +51,13 @@ public class PortUtilsTests
|
|||||||
var url = "http://wiremock.net:1234";
|
var url = "http://wiremock.net:1234";
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var proto, out var host, out var port);
|
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var scheme, out var host, out var port);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.Should().BeTrue();
|
result.Should().BeTrue();
|
||||||
isHttps.Should().BeFalse();
|
isHttps.Should().BeFalse();
|
||||||
isGrpc.Should().BeFalse();
|
isGrpc.Should().BeFalse();
|
||||||
proto.Should().Be("http");
|
scheme.Should().Be("http");
|
||||||
host.Should().Be("wiremock.net");
|
host.Should().Be("wiremock.net");
|
||||||
port.Should().Be(1234);
|
port.Should().Be(1234);
|
||||||
}
|
}
|
||||||
@@ -69,13 +69,13 @@ public class PortUtilsTests
|
|||||||
var url = "https://wiremock.net:5000";
|
var url = "https://wiremock.net:5000";
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var proto, out var host, out var port);
|
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var scheme, out var host, out var port);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.Should().BeTrue();
|
result.Should().BeTrue();
|
||||||
isHttps.Should().BeTrue();
|
isHttps.Should().BeTrue();
|
||||||
isGrpc.Should().BeFalse();
|
isGrpc.Should().BeFalse();
|
||||||
proto.Should().Be("https");
|
scheme.Should().Be("https");
|
||||||
host.Should().Be("wiremock.net");
|
host.Should().Be("wiremock.net");
|
||||||
port.Should().Be(5000);
|
port.Should().Be(5000);
|
||||||
}
|
}
|
||||||
@@ -87,13 +87,13 @@ public class PortUtilsTests
|
|||||||
var url = "grpc://wiremock.net:1234";
|
var url = "grpc://wiremock.net:1234";
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var proto, out var host, out var port);
|
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var scheme, out var host, out var port);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.Should().BeTrue();
|
result.Should().BeTrue();
|
||||||
isHttps.Should().BeFalse();
|
isHttps.Should().BeFalse();
|
||||||
isGrpc.Should().BeTrue();
|
isGrpc.Should().BeTrue();
|
||||||
proto.Should().Be("grpc");
|
scheme.Should().Be("grpc");
|
||||||
host.Should().Be("wiremock.net");
|
host.Should().Be("wiremock.net");
|
||||||
port.Should().Be(1234);
|
port.Should().Be(1234);
|
||||||
}
|
}
|
||||||
@@ -105,13 +105,13 @@ public class PortUtilsTests
|
|||||||
var url = "https://0.0.0.0:5000";
|
var url = "https://0.0.0.0:5000";
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var proto, out var host, out var port);
|
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var scheme, out var host, out var port);
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
result.Should().BeTrue();
|
result.Should().BeTrue();
|
||||||
isHttps.Should().BeTrue();
|
isHttps.Should().BeTrue();
|
||||||
isGrpc.Should().BeFalse();
|
isGrpc.Should().BeFalse();
|
||||||
proto.Should().Be("https");
|
scheme.Should().Be("https");
|
||||||
host.Should().Be("0.0.0.0");
|
host.Should().Be("0.0.0.0");
|
||||||
port.Should().Be(5000);
|
port.Should().Be(5000);
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user