mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-22 16:58:58 +02:00
WireMock.Net.Testcontainers: implement watching the static mapping folder for changes (#1189)
* WireMock.Net.Testcontainers: implement watching the static mapping files + folder for changes * ReloadStaticMappings * fix * . * . * . * . * . * . * . * CopyAsync * <VersionPrefix>1.6.7-preview-02</VersionPrefix> * <VersionPrefix>1.6.7-preview-03</VersionPrefix>
This commit is contained in:
28
.github/workflows/ci.yml
vendored
28
.github/workflows/ci.yml
vendored
@@ -19,11 +19,14 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 'Execute Tests'
|
- name: 'WireMock.Net.Tests'
|
||||||
run: |
|
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
||||||
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
|
||||||
dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
|
- name: 'WireMock.Net.TUnitTests'
|
||||||
dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
|
run: dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
|
||||||
|
|
||||||
|
- name: 'WireMock.Net.Middleware.Tests'
|
||||||
|
run: dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
|
||||||
|
|
||||||
linux-build-and-run:
|
linux-build-and-run:
|
||||||
name: Run Tests on Linux
|
name: Run Tests on Linux
|
||||||
@@ -35,14 +38,17 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: 'Execute Tests'
|
- name: 'WireMock.Net.Tests'
|
||||||
run: |
|
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
||||||
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
|
||||||
dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
|
- name: 'WireMock.Net.TUnitTests'
|
||||||
dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
|
run: dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
|
||||||
|
|
||||||
|
- name: 'WireMock.Net.Middleware.Tests'
|
||||||
|
run: dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
|
||||||
|
|
||||||
- name: Install .NET Aspire workload
|
- name: Install .NET Aspire workload
|
||||||
run: dotnet workload install aspire
|
run: dotnet workload install aspire
|
||||||
|
|
||||||
- name: 'Execute .NET Aspire Tests'
|
- name: 'WireMock.Net.Aspire.Tests'
|
||||||
run: dotnet test './test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj' -c Release
|
run: dotnet test './test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj' -c Release
|
||||||
@@ -138,7 +138,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TUnit", "src\W
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TUnitTests", "test\WireMock.Net.TUnitTests\WireMock.Net.TUnitTests.csproj", "{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TUnitTests", "test\WireMock.Net.TUnitTests\WireMock.Net.TUnitTests.csproj", "{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.WebApplication", "examples\WireMock.Net.WebApplication\WireMock.Net.WebApplication.csproj", "{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.WebApplication", "examples\WireMock.Net.WebApplication\WireMock.Net.WebApplication.csproj", "{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.AspNetCore.Middleware", "src\WireMock.Net.AspNetCore.Middleware\WireMock.Net.AspNetCore.Middleware.csproj", "{B6269AAC-170A-4346-8B9A-579DED3D9A13}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.AspNetCore.Middleware", "src\WireMock.Net.AspNetCore.Middleware\WireMock.Net.AspNetCore.Middleware.csproj", "{B6269AAC-170A-4346-8B9A-579DED3D9A13}"
|
||||||
EndProject
|
EndProject
|
||||||
|
|||||||
@@ -53,15 +53,25 @@ jobs:
|
|||||||
inputs:
|
inputs:
|
||||||
script: |
|
script: |
|
||||||
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-xunit.xml"
|
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-xunit.xml"
|
||||||
|
displayName: 'WireMock.Net.Tests with Coverage'
|
||||||
|
|
||||||
|
- task: CmdLine@2
|
||||||
|
inputs:
|
||||||
|
script: |
|
||||||
dotnet-coverage collect "dotnet test ./test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-tunit.xml"
|
dotnet-coverage collect "dotnet test ./test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-tunit.xml"
|
||||||
|
displayName: 'WireMock.Net.TUnitTests with Coverage'
|
||||||
|
|
||||||
|
- task: CmdLine@2
|
||||||
|
inputs:
|
||||||
|
script: |
|
||||||
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-middleware.xml"
|
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-middleware.xml"
|
||||||
displayName: 'Execute WireMock.Net.Tests with Coverage'
|
displayName: 'WireMock.Net.Middleware.Tests with Coverage'
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
inputs:
|
inputs:
|
||||||
script: |
|
script: |
|
||||||
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-aspire.xml"
|
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-aspire.xml"
|
||||||
displayName: 'Execute WireMock.Net.Aspire.Tests with Coverage'
|
displayName: 'WireMock.Net.Aspire.Tests with Coverage'
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
displayName: 'Merge coverage files'
|
displayName: 'Merge coverage files'
|
||||||
@@ -105,18 +115,25 @@ jobs:
|
|||||||
version: '8.0.x'
|
version: '8.0.x'
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: DotNetCoreCLI@2
|
||||||
displayName: 'Build Unit tests'
|
displayName: 'WireMock.Net.Tests with Coverage'
|
||||||
inputs:
|
|
||||||
command: 'build'
|
|
||||||
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
|
||||||
arguments: '--configuration Debug --framework net8.0'
|
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
|
||||||
displayName: 'Execute Unit Tests with Coverage'
|
|
||||||
inputs:
|
inputs:
|
||||||
command: 'test'
|
command: 'test'
|
||||||
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
||||||
arguments: '--no-build --configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
displayName: 'WireMock.Net.TUnitTests with Coverage'
|
||||||
|
inputs:
|
||||||
|
command: 'test'
|
||||||
|
projects: './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj'
|
||||||
|
arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
||||||
|
|
||||||
|
- task: DotNetCoreCLI@2
|
||||||
|
displayName: 'WireMock.Net.Middleware.Tests with Coverage'
|
||||||
|
inputs:
|
||||||
|
command: 'test'
|
||||||
|
projects: './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj'
|
||||||
|
arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
||||||
|
|
||||||
- job: Windows_Release_to_MyGet
|
- job: Windows_Release_to_MyGet
|
||||||
dependsOn: Windows_Build_Test
|
dependsOn: Windows_Build_Test
|
||||||
|
|||||||
@@ -2,15 +2,16 @@ using AspireApp1.AppHost;
|
|||||||
|
|
||||||
var builder = DistributedApplication.CreateBuilder(args);
|
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(), "WireMockMappings");
|
||||||
|
|
||||||
//IResourceBuilder<WireMockServerResource> apiService = builder
|
IResourceBuilder<WireMockServerResource> apiService = builder
|
||||||
// .AddWireMock("apiservice", WireMockServerArguments.DefaultPort)
|
.AddWireMock("apiservice", WireMockServerArguments.DefaultPort)
|
||||||
// .WithMappingsPath(mappingsPath)
|
.WithMappingsPath(mappingsPath)
|
||||||
// .WithReadStaticMappings()
|
.WithReadStaticMappings()
|
||||||
// .WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync);
|
.WithWatchStaticMappings()
|
||||||
|
.WithApiMappingBuilder(WeatherForecastApiMock.BuildAsync);
|
||||||
|
|
||||||
//var apiServiceUsedForDocs = builder
|
//var apiServiceUsedForDocs = builder
|
||||||
// .AddWireMock("apiservice1", WireMockServerArguments.DefaultPort)
|
// .AddWireMock("apiservice1", WireMockServerArguments.DefaultPort)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ namespace AspireApp1.AppHost;
|
|||||||
|
|
||||||
internal class WeatherForecastApiMock
|
internal class WeatherForecastApiMock
|
||||||
{
|
{
|
||||||
public static async Task BuildAsync(AdminApiMappingBuilder builder)
|
public static async Task BuildAsync(AdminApiMappingBuilder builder, CancellationToken cancellationToken)
|
||||||
{
|
{
|
||||||
var summaries = new[]
|
var summaries = new[]
|
||||||
{
|
{
|
||||||
@@ -29,7 +29,7 @@ internal class WeatherForecastApiMock
|
|||||||
)
|
)
|
||||||
);
|
);
|
||||||
|
|
||||||
await builder.BuildAndPostAsync();
|
await builder.BuildAndPostAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using DotNet.Testcontainers.Configurations;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using WireMock.Net.Testcontainers;
|
using WireMock.Net.Testcontainers;
|
||||||
@@ -12,6 +13,32 @@ internal class Program
|
|||||||
{
|
{
|
||||||
var original = Console.ForegroundColor;
|
var original = Console.ForegroundColor;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkGreen;
|
||||||
|
Console.WriteLine("Copy");
|
||||||
|
await TestCopyAsync();
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = original;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = ConsoleColor.DarkRed;
|
||||||
|
Console.WriteLine("Automatic");
|
||||||
|
await TestAsync();
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
Console.ForegroundColor = original;
|
||||||
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||||
@@ -91,17 +118,44 @@ internal class Program
|
|||||||
{
|
{
|
||||||
Console.ForegroundColor = original;
|
Console.ForegroundColor = original;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try
|
private static async Task TestCopyAsync()
|
||||||
|
{
|
||||||
|
var builder = new WireMockContainerBuilder()
|
||||||
|
.WithWatchStaticMappings(true)
|
||||||
|
.WithAutoRemove(true)
|
||||||
|
.WithCleanUp(true);
|
||||||
|
|
||||||
|
var container = builder.Build();
|
||||||
|
|
||||||
|
await container.StartAsync();
|
||||||
|
|
||||||
|
if (await GetImageOSAsync.Value == OSPlatform.Linux)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
try
|
||||||
Console.WriteLine("Automatic");
|
{
|
||||||
await TestAsync();
|
await container.CopyAsync(@"C:\temp-wiremock\__admin\mappings\StefBodyAsFileExample.json", "/app/__admin/mappings");
|
||||||
}
|
}
|
||||||
finally
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
Console.ForegroundColor = original;
|
Console.WriteLine(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Console.WriteLine("PublicUrl = " + container.GetPublicUrl());
|
||||||
|
|
||||||
|
var adminClient = container.CreateWireMockAdminClient();
|
||||||
|
|
||||||
|
var mappings = await adminClient.GetMappingsAsync();
|
||||||
|
Console.WriteLine("mappings = " + JsonConvert.SerializeObject(mappings, Formatting.Indented));
|
||||||
|
|
||||||
|
await Task.Delay(1_000);
|
||||||
|
|
||||||
|
//Console.WriteLine("Press any key to stop.");
|
||||||
|
//Console.ReadKey();
|
||||||
|
|
||||||
|
await container.StopAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task TestAsync(string? image = null)
|
private static async Task TestAsync(string? image = null)
|
||||||
@@ -129,10 +183,12 @@ internal class Program
|
|||||||
|
|
||||||
await container.StartAsync();
|
await container.StartAsync();
|
||||||
|
|
||||||
await Task.Delay(1_000);
|
await container.ReloadStaticMappingsAsync();
|
||||||
|
|
||||||
var logs = await container.GetLogsAsync(DateTime.Now.AddDays(-1));
|
//var logs = await container.GetLogsAsync(DateTime.Now.AddDays(-1));
|
||||||
Console.WriteLine("logs = " + logs.Stdout);
|
//Console.WriteLine("logs = " + logs.Stdout);
|
||||||
|
|
||||||
|
Console.WriteLine("PublicUrl = " + container.GetPublicUrl());
|
||||||
|
|
||||||
var restEaseApiClient = container.CreateWireMockAdminClient();
|
var restEaseApiClient = container.CreateWireMockAdminClient();
|
||||||
|
|
||||||
@@ -140,12 +196,32 @@ internal class Program
|
|||||||
Console.WriteLine("settings = " + JsonConvert.SerializeObject(settings, Formatting.Indented));
|
Console.WriteLine("settings = " + JsonConvert.SerializeObject(settings, Formatting.Indented));
|
||||||
|
|
||||||
var mappings = await restEaseApiClient.GetMappingsAsync();
|
var mappings = await restEaseApiClient.GetMappingsAsync();
|
||||||
Console.WriteLine("mappings = " + JsonConvert.SerializeObject(mappings, Formatting.Indented));
|
Console.WriteLine("mappingsStef = " + JsonConvert.SerializeObject(mappings, Formatting.Indented));
|
||||||
|
|
||||||
var client = container.CreateClient();
|
var client = container.CreateClient();
|
||||||
var result = await client.GetStringAsync("/static/mapping");
|
var result = await client.GetStringAsync("/static/mapping");
|
||||||
Console.WriteLine("result = " + result);
|
Console.WriteLine("result = " + result);
|
||||||
|
|
||||||
|
//if (image == null)
|
||||||
|
//{
|
||||||
|
// Console.WriteLine("Press any key to stop.");
|
||||||
|
// Console.ReadKey();
|
||||||
|
//}
|
||||||
|
|
||||||
await container.StopAsync();
|
await container.StopAsync();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static Lazy<Task<OSPlatform>> GetImageOSAsync = new(async () =>
|
||||||
|
{
|
||||||
|
if (TestcontainersSettings.OS.DockerEndpointAuthConfig == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"The {nameof(TestcontainersSettings.OS.DockerEndpointAuthConfig)} is null. Check if Docker is started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
using var dockerClientConfig = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration();
|
||||||
|
using var dockerClient = dockerClientConfig.CreateClient();
|
||||||
|
|
||||||
|
var version = await dockerClient.System.GetVersionAsync();
|
||||||
|
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
|
||||||
|
});
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using Aspire.Hosting.ApplicationModel;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Aspire.Extensions;
|
||||||
|
|
||||||
|
internal static class ResourceLoggerServiceExtensions
|
||||||
|
{
|
||||||
|
public static void SetLogger(this ResourceLoggerService resourceLoggerService, WireMockServerResource wireMockServerResource)
|
||||||
|
{
|
||||||
|
var logger = resourceLoggerService.GetLogger(wireMockServerResource);
|
||||||
|
wireMockServerResource.SetLogger(logger);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -30,6 +30,10 @@
|
|||||||
<None Include="../../resources/WireMock.Net-LogoAspire.png" Pack="true" PackagePath="" />
|
<None Include="../../resources/WireMock.Net-LogoAspire.png" Pack="true" PackagePath="" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<Compile Include="..\WireMock.Net\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ public class WireMockServerArguments
|
|||||||
///
|
///
|
||||||
/// Default value is <c>false</c>.
|
/// Default value is <c>false</c>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool WithWatchStaticMappings { get; set; }
|
public bool WatchStaticMappings { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Specifies the path for the (static) mapping json files.
|
/// Specifies the path for the (static) mapping json files.
|
||||||
@@ -65,7 +65,7 @@ public class WireMockServerArguments
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Optional delegate that will be invoked to configure the WireMock.Net resource using the <see cref="AdminApiMappingBuilder"/>.
|
/// Optional delegate that will be invoked to configure the WireMock.Net resource using the <see cref="AdminApiMappingBuilder"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<AdminApiMappingBuilder, Task>? ApiMappingBuilder { get; set; }
|
public Func<AdminApiMappingBuilder, CancellationToken, Task>? ApiMappingBuilder { get; set; }
|
||||||
|
|
||||||
/// <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.
|
||||||
@@ -88,7 +88,7 @@ public class WireMockServerArguments
|
|||||||
Add(args, "--ReadStaticMappings", "true");
|
Add(args, "--ReadStaticMappings", "true");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (WithWatchStaticMappings)
|
if (WatchStaticMappings)
|
||||||
{
|
{
|
||||||
Add(args, "--ReadStaticMappings", "true");
|
Add(args, "--ReadStaticMappings", "true");
|
||||||
Add(args, "--WatchStaticMappings", "true");
|
Add(args, "--WatchStaticMappings", "true");
|
||||||
|
|||||||
@@ -112,7 +112,7 @@ public static class WireMockServerBuilderExtensions
|
|||||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||||
public static IResourceBuilder<WireMockServerResource> WithWatchStaticMappings(this IResourceBuilder<WireMockServerResource> wiremock)
|
public static IResourceBuilder<WireMockServerResource> WithWatchStaticMappings(this IResourceBuilder<WireMockServerResource> wiremock)
|
||||||
{
|
{
|
||||||
Guard.NotNull(wiremock).Resource.Arguments.WithWatchStaticMappings = true;
|
Guard.NotNull(wiremock).Resource.Arguments.WatchStaticMappings = true;
|
||||||
return wiremock;
|
return wiremock;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -124,8 +124,10 @@ public static class WireMockServerBuilderExtensions
|
|||||||
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
/// <returns>A reference to the <see cref="IResourceBuilder{WireMockServerResource}"/>.</returns>
|
||||||
public static IResourceBuilder<WireMockServerResource> WithMappingsPath(this IResourceBuilder<WireMockServerResource> wiremock, string mappingsPath)
|
public static IResourceBuilder<WireMockServerResource> WithMappingsPath(this IResourceBuilder<WireMockServerResource> wiremock, string mappingsPath)
|
||||||
{
|
{
|
||||||
return Guard.NotNull(wiremock)
|
Guard.NotNullOrWhiteSpace(mappingsPath);
|
||||||
.WithBindMount(Guard.NotNullOrWhiteSpace(mappingsPath), DefaultLinuxMappingsPath);
|
Guard.NotNull(wiremock).Resource.Arguments.MappingsPath = mappingsPath;
|
||||||
|
|
||||||
|
return wiremock.WithBindMount(mappingsPath, DefaultLinuxMappingsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -151,6 +153,17 @@ public static class WireMockServerBuilderExtensions
|
|||||||
/// <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></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));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use WireMock Client's AdminApiMappingBuilder to configure the WireMock.Net resource.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="wiremock">The <see cref="IResourceBuilder{WireMockServerResource}"/>.</param>
|
||||||
|
/// <param name="configure">Delegate that will be invoked to configure the WireMock.Net resource.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static IResourceBuilder<WireMockServerResource> WithApiMappingBuilder(this IResourceBuilder<WireMockServerResource> wiremock, Func<AdminApiMappingBuilder, CancellationToken, Task> configure)
|
||||||
{
|
{
|
||||||
Guard.NotNull(wiremock);
|
Guard.NotNull(wiremock);
|
||||||
|
|
||||||
|
|||||||
@@ -3,50 +3,39 @@
|
|||||||
using Aspire.Hosting.ApplicationModel;
|
using Aspire.Hosting.ApplicationModel;
|
||||||
using Aspire.Hosting.Lifecycle;
|
using Aspire.Hosting.Lifecycle;
|
||||||
using Microsoft.Extensions.Logging;
|
using Microsoft.Extensions.Logging;
|
||||||
using RestEase;
|
|
||||||
using WireMock.Client;
|
|
||||||
using WireMock.Client.Extensions;
|
|
||||||
|
|
||||||
namespace WireMock.Net.Aspire;
|
namespace WireMock.Net.Aspire;
|
||||||
|
|
||||||
internal class WireMockServerLifecycleHook(ResourceLoggerService loggerService) : IDistributedApplicationLifecycleHook
|
internal class WireMockServerLifecycleHook(ILoggerFactory loggerFactory) : IDistributedApplicationLifecycleHook, IAsyncDisposable
|
||||||
{
|
{
|
||||||
|
private readonly CancellationTokenSource _shutdownCts = new();
|
||||||
|
|
||||||
public async Task AfterResourcesCreatedAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
|
public async Task AfterResourcesCreatedAsync(DistributedApplicationModel appModel, CancellationToken cancellationToken = default)
|
||||||
{
|
{
|
||||||
|
var cts = CancellationTokenSource.CreateLinkedTokenSource(_shutdownCts.Token, cancellationToken);
|
||||||
|
|
||||||
var wireMockServerResources = appModel.Resources
|
var wireMockServerResources = appModel.Resources
|
||||||
.OfType<WireMockServerResource>()
|
.OfType<WireMockServerResource>()
|
||||||
.Where(resource => resource.Arguments.ApiMappingBuilder is not null)
|
|
||||||
.ToArray();
|
.ToArray();
|
||||||
|
|
||||||
if (wireMockServerResources.Length == 0)
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (var wireMockServerResource in wireMockServerResources)
|
foreach (var wireMockServerResource in wireMockServerResources)
|
||||||
{
|
{
|
||||||
|
wireMockServerResource.SetLogger(loggerFactory.CreateLogger<WireMockServerResource>());
|
||||||
|
|
||||||
var endpoint = wireMockServerResource.GetEndpoint();
|
var endpoint = wireMockServerResource.GetEndpoint();
|
||||||
if (endpoint.IsAllocated)
|
if (endpoint.IsAllocated)
|
||||||
{
|
{
|
||||||
var adminApi = CreateWireMockAdminApi(wireMockServerResource);
|
await wireMockServerResource.WaitForHealthAsync(cts.Token);
|
||||||
|
|
||||||
var logger = loggerService.GetLogger(wireMockServerResource);
|
await wireMockServerResource.CallApiMappingBuilderActionAsync(cts.Token);
|
||||||
logger.LogInformation("Checking Health status from WireMock.Net");
|
|
||||||
|
|
||||||
await adminApi.WaitForHealthAsync(cancellationToken: cancellationToken);
|
wireMockServerResource.StartWatchingStaticMappings(cts.Token);
|
||||||
|
|
||||||
logger.LogInformation("Calling ApiMappingBuilder to add mappings to WireMock.Net");
|
|
||||||
var mappingBuilder = adminApi.GetMappingBuilder();
|
|
||||||
await wireMockServerResource.Arguments.ApiMappingBuilder!.Invoke(mappingBuilder);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IWireMockAdminApi CreateWireMockAdminApi(WireMockServerResource resource)
|
public async ValueTask DisposeAsync()
|
||||||
{
|
{
|
||||||
var adminApi = RestClient.For<IWireMockAdminApi>(resource.GetEndpoint().Url);
|
await _shutdownCts.CancelAsync();
|
||||||
return resource.Arguments.HasBasicAuthentication ?
|
|
||||||
adminApi.WithAuthorization(resource.Arguments.AdminUsername!, resource.Arguments.AdminPassword!) :
|
|
||||||
adminApi;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,11 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
using RestEase;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
|
using WireMock.Client;
|
||||||
|
using WireMock.Client.Extensions;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace Aspire.Hosting.ApplicationModel;
|
namespace Aspire.Hosting.ApplicationModel;
|
||||||
@@ -10,7 +15,13 @@ namespace Aspire.Hosting.ApplicationModel;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class WireMockServerResource : ContainerResource, IResourceWithServiceDiscovery
|
public class WireMockServerResource : ContainerResource, IResourceWithServiceDiscovery
|
||||||
{
|
{
|
||||||
|
private const int EnhancedFileSystemWatcherTimeoutMs = 2000;
|
||||||
|
|
||||||
internal WireMockServerArguments Arguments { get; }
|
internal WireMockServerArguments Arguments { get; }
|
||||||
|
internal Lazy<IWireMockAdminApi> AdminApi => new(CreateWireMockAdminApi);
|
||||||
|
|
||||||
|
private ILogger? _logger;
|
||||||
|
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="WireMockServerResource"/> class.
|
/// Initializes a new instance of the <see cref="WireMockServerResource"/> class.
|
||||||
@@ -30,4 +41,82 @@ public class WireMockServerResource : ContainerResource, IResourceWithServiceDis
|
|||||||
{
|
{
|
||||||
return new EndpointReference(this, "http");
|
return new EndpointReference(this, "http");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
internal void SetLogger(ILogger logger)
|
||||||
|
{
|
||||||
|
_logger = logger;
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task WaitForHealthAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
_logger?.LogInformation("Checking Health status from WireMock.Net");
|
||||||
|
await AdminApi.Value.WaitForHealthAsync(cancellationToken: cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal async Task CallApiMappingBuilderActionAsync(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (Arguments.ApiMappingBuilder == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger?.LogInformation("Calling ApiMappingBuilder to add mappings to WireMock.Net");
|
||||||
|
|
||||||
|
var mappingBuilder = AdminApi.Value.GetMappingBuilder();
|
||||||
|
await Arguments.ApiMappingBuilder.Invoke(mappingBuilder, cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal void StartWatchingStaticMappings(CancellationToken cancellationToken)
|
||||||
|
{
|
||||||
|
if (!Arguments.WatchStaticMappings || string.IsNullOrEmpty(Arguments.MappingsPath))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
cancellationToken.Register(() =>
|
||||||
|
{
|
||||||
|
if (_enhancedFileSystemWatcher != null)
|
||||||
|
{
|
||||||
|
_enhancedFileSystemWatcher.EnableRaisingEvents = false;
|
||||||
|
_enhancedFileSystemWatcher.Created -= FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.Changed -= FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.Deleted -= FileCreatedChangedOrDeleted;
|
||||||
|
|
||||||
|
_enhancedFileSystemWatcher.Dispose();
|
||||||
|
_enhancedFileSystemWatcher = null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
_logger?.LogInformation("Starting to watch static mappings on path: '{Path}'. ", Arguments.MappingsPath);
|
||||||
|
|
||||||
|
_enhancedFileSystemWatcher = new EnhancedFileSystemWatcher(Arguments.MappingsPath, "*.json", EnhancedFileSystemWatcherTimeoutMs)
|
||||||
|
{
|
||||||
|
IncludeSubdirectories = true
|
||||||
|
};
|
||||||
|
_enhancedFileSystemWatcher.Created += FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.Changed += FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.Deleted += FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.EnableRaisingEvents = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private IWireMockAdminApi CreateWireMockAdminApi()
|
||||||
|
{
|
||||||
|
var adminApi = RestClient.For<IWireMockAdminApi>(GetEndpoint().Url);
|
||||||
|
return Arguments.HasBasicAuthentication ?
|
||||||
|
adminApi.WithAuthorization(Arguments.AdminUsername!, Arguments.AdminPassword!) :
|
||||||
|
adminApi;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
||||||
|
{
|
||||||
|
_logger?.LogInformation("MappingFile created, changed or deleted: '{0}'. Triggering ReloadStaticMappings.", args.FullPath);
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await AdminApi.Value.ReloadStaticMappingsAsync();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger?.LogWarning(ex, "Error calling /__admin/mappings/reloadStaticMappings");
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -72,7 +72,7 @@ public static class WireMockAdminApiExtensions
|
|||||||
|
|
||||||
if (retries >= MaxRetries)
|
if (retries >= MaxRetries)
|
||||||
{
|
{
|
||||||
throw new InvalidOperationException($"The /__admin/health endpoint did not return 'Healthy' after {MaxRetries} retries and {totalWaitTime / 1000.0:0.0} seconds.");
|
throw new InvalidOperationException($"The /__admin/health endpoint did not return '{HealthStatusHealthy}' after {MaxRetries} retries and {totalWaitTime / 1000.0:0.0} seconds.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -122,6 +122,13 @@ public interface IWireMockAdminApi
|
|||||||
[Post("mappings/reset")]
|
[Post("mappings/reset")]
|
||||||
Task<StatusModel> ResetMappingsAsync(bool? reloadStaticMappings = false, CancellationToken cancellationToken = default);
|
Task<StatusModel> ResetMappingsAsync(bool? reloadStaticMappings = false, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reload the static mappings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Post("mappings/reloadStaticMappings")]
|
||||||
|
Task<StatusModel> ReloadStaticMappingsAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a mapping based on the guid
|
/// Get a mapping based on the guid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using WireMock.Net.Testcontainers.Models;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Testcontainers.Utils;
|
||||||
|
|
||||||
|
internal static class ContainerInfoProvider
|
||||||
|
{
|
||||||
|
public static readonly Dictionary<OSPlatform, ContainerInfo> Info = new()
|
||||||
|
{
|
||||||
|
{ OSPlatform.Linux, new ContainerInfo("sheyenrath/wiremock.net-alpine", "/app/__admin/mappings") },
|
||||||
|
{ OSPlatform.Windows, new ContainerInfo("sheyenrath/wiremock.net-windows", @"c:\app\__admin\mappings") }
|
||||||
|
};
|
||||||
|
}
|
||||||
25
src/WireMock.Net.Testcontainers/Utils/ContainerUtils.cs
Normal file
25
src/WireMock.Net.Testcontainers/Utils/ContainerUtils.cs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Runtime.InteropServices;
|
||||||
|
using DotNet.Testcontainers.Configurations;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Testcontainers.Utils;
|
||||||
|
|
||||||
|
internal static class ContainerUtils
|
||||||
|
{
|
||||||
|
public static Lazy<Task<OSPlatform>> GetImageOSAsync = new(async () =>
|
||||||
|
{
|
||||||
|
if (TestcontainersSettings.OS.DockerEndpointAuthConfig == null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"The {nameof(TestcontainersSettings.OS.DockerEndpointAuthConfig)} is null. Check if Docker is started.");
|
||||||
|
}
|
||||||
|
|
||||||
|
using var dockerClientConfig = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration();
|
||||||
|
using var dockerClient = dockerClientConfig.CreateClient();
|
||||||
|
|
||||||
|
var version = await dockerClient.System.GetVersionAsync();
|
||||||
|
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
|
||||||
|
});
|
||||||
|
}
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="..\WireMock.Net\Http\HttpClientFactory2.cs" Link="Http\HttpClientFactory2.cs" />
|
<Compile Include="..\WireMock.Net\Http\HttpClientFactory2.cs" Link="Http\HttpClientFactory2.cs" />
|
||||||
|
<Compile Include="..\WireMock.Net\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
|
||||||
using Docker.DotNet.Models;
|
using Docker.DotNet.Models;
|
||||||
using DotNet.Testcontainers.Builders;
|
using DotNet.Testcontainers.Builders;
|
||||||
using DotNet.Testcontainers.Configurations;
|
using DotNet.Testcontainers.Configurations;
|
||||||
@@ -19,6 +18,10 @@ public sealed class WireMockConfiguration : ContainerConfiguration
|
|||||||
|
|
||||||
public string? StaticMappingsPath { get; private set; }
|
public string? StaticMappingsPath { get; private set; }
|
||||||
|
|
||||||
|
public bool WatchStaticMappings { get; private set; }
|
||||||
|
|
||||||
|
public bool WatchStaticMappingsInSubdirectories { get; private set; }
|
||||||
|
|
||||||
public bool HasBasicAuthentication => !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
|
public bool HasBasicAuthentication => !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
|
||||||
|
|
||||||
public WireMockConfiguration(string? username = null, string? password = null)
|
public WireMockConfiguration(string? username = null, string? password = null)
|
||||||
@@ -65,16 +68,30 @@ public sealed class WireMockConfiguration : ContainerConfiguration
|
|||||||
Username = BuildConfiguration.Combine(oldValue.Username, newValue.Username);
|
Username = BuildConfiguration.Combine(oldValue.Username, newValue.Username);
|
||||||
Password = BuildConfiguration.Combine(oldValue.Password, newValue.Password);
|
Password = BuildConfiguration.Combine(oldValue.Password, newValue.Password);
|
||||||
StaticMappingsPath = BuildConfiguration.Combine(oldValue.StaticMappingsPath, newValue.StaticMappingsPath);
|
StaticMappingsPath = BuildConfiguration.Combine(oldValue.StaticMappingsPath, newValue.StaticMappingsPath);
|
||||||
|
WatchStaticMappings = BuildConfiguration.Combine(oldValue.WatchStaticMappings, newValue.WatchStaticMappings);
|
||||||
|
WatchStaticMappingsInSubdirectories = BuildConfiguration.Combine(oldValue.WatchStaticMappingsInSubdirectories, newValue.WatchStaticMappingsInSubdirectories);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Set the StaticMappingsPath.
|
/// Set the StaticMappingsPath.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The path which contains the StaticMappings.</param>
|
/// <param name="path">The path which contains the StaticMappings.</param>
|
||||||
/// <returns><see cref="WireMockConfiguration"/> </returns>
|
/// <returns><see cref="WireMockConfiguration"/></returns>
|
||||||
public WireMockConfiguration WithStaticMappingsPath(string path)
|
public WireMockConfiguration WithStaticMappingsPath(string path)
|
||||||
{
|
{
|
||||||
StaticMappingsPath = path;
|
StaticMappingsPath = path;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Watch the static mappings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="includeSubDirectories">Also look in SubDirectories.</param>
|
||||||
|
/// <returns><see cref="WireMockConfiguration"/></returns>
|
||||||
|
public WireMockConfiguration WithWatchStaticMappings(bool includeSubDirectories)
|
||||||
|
{
|
||||||
|
WatchStaticMappings = true;
|
||||||
|
WatchStaticMappingsInSubdirectories = includeSubDirectories;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,20 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.IO;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using DotNet.Testcontainers.Configurations;
|
||||||
using DotNet.Testcontainers.Containers;
|
using DotNet.Testcontainers.Containers;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
using RestEase;
|
using RestEase;
|
||||||
using Stef.Validation;
|
|
||||||
using WireMock.Client;
|
using WireMock.Client;
|
||||||
using WireMock.Client.Extensions;
|
using WireMock.Client.Extensions;
|
||||||
using WireMock.Http;
|
using WireMock.Http;
|
||||||
|
using WireMock.Net.Testcontainers.Utils;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Net.Testcontainers;
|
namespace WireMock.Net.Testcontainers;
|
||||||
|
|
||||||
@@ -17,17 +23,23 @@ namespace WireMock.Net.Testcontainers;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public sealed class WireMockContainer : DockerContainer
|
public sealed class WireMockContainer : DockerContainer
|
||||||
{
|
{
|
||||||
|
private const int EnhancedFileSystemWatcherTimeoutMs = 2000;
|
||||||
internal const int ContainerPort = 80;
|
internal const int ContainerPort = 80;
|
||||||
|
|
||||||
private readonly WireMockConfiguration _configuration;
|
private readonly WireMockConfiguration _configuration;
|
||||||
|
|
||||||
|
private IWireMockAdminApi? _adminApi;
|
||||||
|
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="WireMockContainer" /> class.
|
/// Initializes a new instance of the <see cref="WireMockContainer" /> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="configuration">The container configuration.</param>
|
/// <param name="configuration">The container configuration.</param>
|
||||||
public WireMockContainer(WireMockConfiguration configuration) : base(configuration)
|
public WireMockContainer(WireMockConfiguration configuration) : base(configuration)
|
||||||
{
|
{
|
||||||
_configuration = Guard.NotNull(configuration);
|
_configuration = Stef.Validation.Guard.NotNull(configuration);
|
||||||
|
|
||||||
|
Started += WireMockContainer_Started;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -92,6 +104,71 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
return client;
|
return client;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Copies a test host directory or file to the container and triggers a reload of the static mappings if required.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="source">The source directory or file to be copied.</param>
|
||||||
|
/// <param name="target">The target directory path to copy the files to.</param>
|
||||||
|
/// <param name="fileMode">The POSIX file mode permission.</param>
|
||||||
|
/// <param name="ct">Cancellation token.</param>
|
||||||
|
/// <returns>A task that completes when the directory or file has been copied.</returns>
|
||||||
|
public new async Task CopyAsync(string source, string target, UnixFileModes fileMode = Unix.FileMode644, CancellationToken ct = default)
|
||||||
|
{
|
||||||
|
await base.CopyAsync(source, target, fileMode, ct);
|
||||||
|
|
||||||
|
if (_configuration.WatchStaticMappings && await PathStartsWithContainerMappingsPath(target))
|
||||||
|
{
|
||||||
|
await ReloadStaticMappingsAsync(target, ct);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reload the static mappings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
public async Task ReloadStaticMappingsAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
if (_adminApi == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await _adminApi.ReloadStaticMappingsAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogWarning(ex, "Error calling /__admin/mappings/reloadStaticMappings");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
protected override ValueTask DisposeAsyncCore()
|
||||||
|
{
|
||||||
|
if (_enhancedFileSystemWatcher != null)
|
||||||
|
{
|
||||||
|
_enhancedFileSystemWatcher.EnableRaisingEvents = false;
|
||||||
|
_enhancedFileSystemWatcher.Created -= FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.Changed -= FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.Deleted -= FileCreatedChangedOrDeleted;
|
||||||
|
|
||||||
|
_enhancedFileSystemWatcher.Dispose();
|
||||||
|
_enhancedFileSystemWatcher = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
Started -= WireMockContainer_Started;
|
||||||
|
|
||||||
|
return base.DisposeAsyncCore();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<bool> PathStartsWithContainerMappingsPath(string value)
|
||||||
|
{
|
||||||
|
var imageOs = await ContainerUtils.GetImageOSAsync.Value;
|
||||||
|
|
||||||
|
return value.StartsWith(ContainerInfoProvider.Info[imageOs].MappingsPath);
|
||||||
|
}
|
||||||
|
|
||||||
private void ValidateIfRunning()
|
private void ValidateIfRunning()
|
||||||
{
|
{
|
||||||
if (State != TestcontainersStates.Running)
|
if (State != TestcontainersStates.Running)
|
||||||
@@ -100,5 +177,35 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void WireMockContainer_Started(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
_adminApi = CreateWireMockAdminClient();
|
||||||
|
|
||||||
|
if (!_configuration.WatchStaticMappings || string.IsNullOrEmpty(_configuration.StaticMappingsPath))
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_enhancedFileSystemWatcher = new EnhancedFileSystemWatcher(_configuration.StaticMappingsPath!, "*.json", EnhancedFileSystemWatcherTimeoutMs)
|
||||||
|
{
|
||||||
|
IncludeSubdirectories = _configuration.WatchStaticMappingsInSubdirectories
|
||||||
|
};
|
||||||
|
_enhancedFileSystemWatcher.Created += FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.Changed += FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.Deleted += FileCreatedChangedOrDeleted;
|
||||||
|
_enhancedFileSystemWatcher.EnableRaisingEvents = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
||||||
|
{
|
||||||
|
await ReloadStaticMappingsAsync(args.FullPath);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task ReloadStaticMappingsAsync(string path, CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
Logger.LogInformation("MappingFile created, changed or deleted: '{Path}'. Triggering ReloadStaticMappings.", path);
|
||||||
|
await ReloadStaticMappingsAsync(cancellationToken);
|
||||||
|
}
|
||||||
|
|
||||||
private Uri GetPublicUri() => new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(ContainerPort)).Uri;
|
private Uri GetPublicUri() => new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(ContainerPort)).Uri;
|
||||||
}
|
}
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Docker.DotNet.Models;
|
using Docker.DotNet.Models;
|
||||||
using DotNet.Testcontainers.Builders;
|
using DotNet.Testcontainers.Builders;
|
||||||
using DotNet.Testcontainers.Configurations;
|
using DotNet.Testcontainers.Configurations;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Net.Testcontainers.Models;
|
using WireMock.Net.Testcontainers.Utils;
|
||||||
|
|
||||||
namespace WireMock.Net.Testcontainers;
|
namespace WireMock.Net.Testcontainers;
|
||||||
|
|
||||||
@@ -19,26 +17,6 @@ namespace WireMock.Net.Testcontainers;
|
|||||||
public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContainerBuilder, WireMockContainer, WireMockConfiguration>
|
public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContainerBuilder, WireMockContainer, WireMockConfiguration>
|
||||||
{
|
{
|
||||||
private const string DefaultLogger = "WireMockConsoleLogger";
|
private const string DefaultLogger = "WireMockConsoleLogger";
|
||||||
private readonly Dictionary<OSPlatform, ContainerInfo> _info = new()
|
|
||||||
{
|
|
||||||
{ OSPlatform.Linux, new ContainerInfo("sheyenrath/wiremock.net-alpine", "/app/__admin/mappings") },
|
|
||||||
{ OSPlatform.Windows, new ContainerInfo("sheyenrath/wiremock.net-windows", @"c:\app\__admin\mappings") }
|
|
||||||
};
|
|
||||||
|
|
||||||
private readonly Lazy<Task<OSPlatform>> _getOSAsLazy = new(async () =>
|
|
||||||
{
|
|
||||||
if (TestcontainersSettings.OS.DockerEndpointAuthConfig == null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException($"The {nameof(TestcontainersSettings.OS.DockerEndpointAuthConfig)} is null. Check if Docker is started.");
|
|
||||||
}
|
|
||||||
|
|
||||||
using var dockerClientConfig = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration();
|
|
||||||
using var dockerClient = dockerClientConfig.CreateClient();
|
|
||||||
|
|
||||||
var version = await dockerClient.System.GetVersionAsync();
|
|
||||||
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
|
|
||||||
});
|
|
||||||
|
|
||||||
private OSPlatform? _imageOS;
|
private OSPlatform? _imageOS;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -58,7 +36,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public WireMockContainerBuilder WithImage()
|
public WireMockContainerBuilder WithImage()
|
||||||
{
|
{
|
||||||
_imageOS ??= _getOSAsLazy.Value.GetAwaiter().GetResult();
|
_imageOS ??= ContainerUtils.GetImageOSAsync.Value.GetAwaiter().GetResult();
|
||||||
return WithImage(_imageOS.Value);
|
return WithImage(_imageOS.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -130,7 +108,9 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public WireMockContainerBuilder WithWatchStaticMappings(bool includeSubDirectories)
|
public WireMockContainerBuilder WithWatchStaticMappings(bool includeSubDirectories)
|
||||||
{
|
{
|
||||||
return WithCommand("--WatchStaticMappings true").WithCommand($"--WatchStaticMappingsInSubdirectories {includeSubDirectories}");
|
return Merge(DockerResourceConfiguration, DockerResourceConfiguration.WithWatchStaticMappings(includeSubDirectories))
|
||||||
|
.WithCommand("--WatchStaticMappings true")
|
||||||
|
.WithCommand($"--WatchStaticMappingsInSubdirectories {includeSubDirectories}");
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -181,7 +161,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
|
|
||||||
if (!string.IsNullOrEmpty(builder.DockerResourceConfiguration.StaticMappingsPath))
|
if (!string.IsNullOrEmpty(builder.DockerResourceConfiguration.StaticMappingsPath))
|
||||||
{
|
{
|
||||||
builder = builder.WithBindMount(builder.DockerResourceConfiguration.StaticMappingsPath, _info[_imageOS.Value].MappingsPath);
|
builder = builder.WithBindMount(builder.DockerResourceConfiguration.StaticMappingsPath, ContainerInfoProvider.Info[_imageOS.Value].MappingsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
builder.Validate();
|
builder.Validate();
|
||||||
@@ -198,7 +178,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
return builder
|
return builder
|
||||||
.WithPortBinding(WireMockContainer.ContainerPort, true)
|
.WithPortBinding(WireMockContainer.ContainerPort, true)
|
||||||
.WithCommand($"--WireMockLogger {DefaultLogger}")
|
.WithCommand($"--WireMockLogger {DefaultLogger}")
|
||||||
.WithWaitStrategy(waitForContainerOS.UntilMessageIsLogged("By Stef Heyenrath"));
|
.WithWaitStrategy(waitForContainerOS.UntilMessageIsLogged("WireMock.Net server running"));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
@@ -222,6 +202,6 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
private WireMockContainerBuilder WithImage(OSPlatform os)
|
private WireMockContainerBuilder WithImage(OSPlatform os)
|
||||||
{
|
{
|
||||||
_imageOS = os;
|
_imageOS = os;
|
||||||
return WithImage(_info[os].Image);
|
return WithImage(ContainerInfoProvider.Info[os].Image);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,6 +96,9 @@ public partial class WireMockServer
|
|||||||
// __admin/mappings/reset
|
// __admin/mappings/reset
|
||||||
Given(Request.Create().WithPath(_adminPaths.Mappings + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsReset));
|
Given(Request.Create().WithPath(_adminPaths.Mappings + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingsReset));
|
||||||
|
|
||||||
|
// __admin/mappings/reloadStaticMappings
|
||||||
|
Given(Request.Create().WithPath(_adminPaths.Mappings + "/reloadStaticMappings").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ReloadStaticMappings));
|
||||||
|
|
||||||
// __admin/mappings/{guid}
|
// __admin/mappings/{guid}
|
||||||
Given(Request.Create().WithPath(_adminPaths.MappingsGuidPathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingGet));
|
Given(Request.Create().WithPath(_adminPaths.MappingsGuidPathMatcher).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingGet));
|
||||||
Given(Request.Create().WithPath(_adminPaths.MappingsGuidPathMatcher).UsingPut().WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingPut));
|
Given(Request.Create().WithPath(_adminPaths.MappingsGuidPathMatcher).UsingPut().WithHeader(HttpKnownHeaderNames.ContentType, AdminRequestContentTypeJson)).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(MappingPut));
|
||||||
@@ -170,9 +173,9 @@ public partial class WireMockServer
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (string filename in _settings.FileSystemHandler.EnumerateFiles(folder, _settings.WatchStaticMappingsInSubdirectories == true).OrderBy(f => f))
|
foreach (var filename in _settings.FileSystemHandler.EnumerateFiles(folder, _settings.WatchStaticMappingsInSubdirectories == true).OrderBy(f => f))
|
||||||
{
|
{
|
||||||
_settings.Logger.Info("Reading Static MappingFile : '{0}'", filename);
|
_settings.Logger.Info("Reading Static MappingFile : '{0}'.", filename);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -556,18 +559,25 @@ public partial class WireMockServer
|
|||||||
|
|
||||||
ResetScenarios();
|
ResetScenarios();
|
||||||
|
|
||||||
string message = "Mappings reset";
|
var message = "Mappings reset";
|
||||||
if (requestMessage.Query != null &&
|
if (requestMessage.Query != null &&
|
||||||
requestMessage.Query.ContainsKey(QueryParamReloadStaticMappings) &&
|
requestMessage.Query.ContainsKey(QueryParamReloadStaticMappings) &&
|
||||||
bool.TryParse(requestMessage.Query[QueryParamReloadStaticMappings].ToString(), out bool reloadStaticMappings) &&
|
bool.TryParse(requestMessage.Query[QueryParamReloadStaticMappings].ToString(), out var reloadStaticMappings) &&
|
||||||
reloadStaticMappings)
|
reloadStaticMappings)
|
||||||
{
|
{
|
||||||
ReadStaticMappings();
|
ReadStaticMappings();
|
||||||
message = $"{message} and static mappings reloaded";
|
message += " and static mappings reloaded";
|
||||||
}
|
}
|
||||||
|
|
||||||
return ResponseMessageBuilder.Create(200, message);
|
return ResponseMessageBuilder.Create(200, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IResponseMessage ReloadStaticMappings(IRequestMessage _)
|
||||||
|
{
|
||||||
|
ReadStaticMappings();
|
||||||
|
|
||||||
|
return ResponseMessageBuilder.Create(200, "Static Mappings reloaded");
|
||||||
|
}
|
||||||
#endregion Mappings
|
#endregion Mappings
|
||||||
|
|
||||||
#region Request/{guid}
|
#region Request/{guid}
|
||||||
@@ -780,7 +790,7 @@ public partial class WireMockServer
|
|||||||
private void EnhancedFileSystemWatcherDeleted(object sender, FileSystemEventArgs args)
|
private void EnhancedFileSystemWatcherDeleted(object sender, FileSystemEventArgs args)
|
||||||
{
|
{
|
||||||
_settings.Logger.Info("MappingFile deleted : '{0}'", args.FullPath);
|
_settings.Logger.Info("MappingFile deleted : '{0}'", args.FullPath);
|
||||||
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(args.FullPath);
|
var filenameWithoutExtension = Path.GetFileNameWithoutExtension(args.FullPath);
|
||||||
|
|
||||||
if (Guid.TryParse(filenameWithoutExtension, out var guidFromFilename))
|
if (Guid.TryParse(filenameWithoutExtension, out var guidFromFilename))
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ public class WireMockServerArgumentsTests
|
|||||||
args.AdminUsername.Should().BeNull();
|
args.AdminUsername.Should().BeNull();
|
||||||
args.AdminPassword.Should().BeNull();
|
args.AdminPassword.Should().BeNull();
|
||||||
args.ReadStaticMappings.Should().BeFalse();
|
args.ReadStaticMappings.Should().BeFalse();
|
||||||
args.WithWatchStaticMappings.Should().BeFalse();
|
args.WatchStaticMappings.Should().BeFalse();
|
||||||
args.MappingsPath.Should().BeNull();
|
args.MappingsPath.Should().BeNull();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -87,7 +87,7 @@ public class WireMockServerArgumentsTests
|
|||||||
// Arrange
|
// Arrange
|
||||||
var args = new WireMockServerArguments
|
var args = new WireMockServerArguments
|
||||||
{
|
{
|
||||||
WithWatchStaticMappings = true,
|
WatchStaticMappings = true,
|
||||||
ReadStaticMappings = readStaticMappings
|
ReadStaticMappings = readStaticMappings
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -104,7 +104,7 @@ public class WireMockServerArgumentsTests
|
|||||||
// Arrange
|
// Arrange
|
||||||
var args = new WireMockServerArguments
|
var args = new WireMockServerArguments
|
||||||
{
|
{
|
||||||
WithWatchStaticMappings = false
|
WatchStaticMappings = false
|
||||||
};
|
};
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ public class WireMockServerBuilderExtensionsTests
|
|||||||
AdminPassword = password,
|
AdminPassword = password,
|
||||||
AdminUsername = username,
|
AdminUsername = username,
|
||||||
ReadStaticMappings = true,
|
ReadStaticMappings = true,
|
||||||
WithWatchStaticMappings = false,
|
WatchStaticMappings = false,
|
||||||
MappingsPath = null,
|
MappingsPath = null,
|
||||||
HttpPort = port
|
HttpPort = port
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1126,5 +1126,19 @@ text
|
|||||||
|
|
||||||
server.Stop();
|
server.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task IWireMockAdminApi_ReadStaticMappingsAsync()
|
||||||
|
{
|
||||||
|
// Arrange
|
||||||
|
using var server = WireMockServer.StartWithAdminInterface();
|
||||||
|
var api = RestClient.For<IWireMockAdminApi>(server.Url);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var status = await api.ReloadStaticMappingsAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
status.Status.Should().Be("Static Mappings reloaded");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -100,7 +100,7 @@ public class WireMockServerProxyTests
|
|||||||
Url = "http://www.google.com",
|
Url = "http://www.google.com",
|
||||||
SaveMapping = true,
|
SaveMapping = true,
|
||||||
SaveMappingToFile = false,
|
SaveMappingToFile = false,
|
||||||
ExcludedHeaders = new[] { "Connection" } // Needed for .NET 4.5.x and 4.6.x
|
ExcludedHeaders = ["Connection"] // Needed for .NET 4.5.x and 4.6.x
|
||||||
},
|
},
|
||||||
StartAdminInterface = true
|
StartAdminInterface = true
|
||||||
};
|
};
|
||||||
@@ -119,7 +119,7 @@ public class WireMockServerProxyTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
server.Mappings.Should().HaveCount(36);
|
server.Mappings.Should().HaveCount(37);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
|
|||||||
@@ -75,6 +75,8 @@ public class WireMockServerSettingsTests
|
|||||||
[Fact]
|
[Fact]
|
||||||
public void WireMockServer_WireMockServerSettings_PriorityFromAllAdminMappingsIsLow_When_StartAdminInterface_IsTrue()
|
public void WireMockServer_WireMockServerSettings_PriorityFromAllAdminMappingsIsLow_When_StartAdminInterface_IsTrue()
|
||||||
{
|
{
|
||||||
|
const int count = 35;
|
||||||
|
|
||||||
// Assign and Act
|
// Assign and Act
|
||||||
var server = WireMockServer.Start(new WireMockServerSettings
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
{
|
{
|
||||||
@@ -83,13 +85,15 @@ public class WireMockServerSettingsTests
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
server.Mappings.Should().NotBeNull();
|
server.Mappings.Should().NotBeNull();
|
||||||
server.Mappings.Should().HaveCount(34);
|
server.Mappings.Should().HaveCount(count);
|
||||||
server.Mappings.All(m => m.Priority == WireMockConstants.AdminPriority).Should().BeTrue();
|
server.Mappings.All(m => m.Priority == WireMockConstants.AdminPriority).Should().BeTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void WireMockServer_WireMockServerSettings_ProxyAndRecordSettings_ProxyPriority_IsMinus2000000_When_StartAdminInterface_IsTrue()
|
public void WireMockServer_WireMockServerSettings_ProxyAndRecordSettings_ProxyPriority_IsMinus2000000_When_StartAdminInterface_IsTrue()
|
||||||
{
|
{
|
||||||
|
const int count = 36;
|
||||||
|
|
||||||
// Assign and Act
|
// Assign and Act
|
||||||
var server = WireMockServer.Start(new WireMockServerSettings
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
{
|
{
|
||||||
@@ -102,9 +106,9 @@ public class WireMockServerSettingsTests
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
server.Mappings.Should().NotBeNull();
|
server.Mappings.Should().NotBeNull();
|
||||||
server.Mappings.Should().HaveCount(35);
|
server.Mappings.Should().HaveCount(count);
|
||||||
|
|
||||||
server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(34);
|
server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(count - 1);
|
||||||
server.Mappings.Count(m => m.Priority == WireMockConstants.ProxyPriority).Should().Be(1);
|
server.Mappings.Count(m => m.Priority == WireMockConstants.ProxyPriority).Should().Be(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user