mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-06-12 01:34:27 +02:00
Add "AddUrl" to WireMockContainerBuilder to support grpc (#1246)
* Add "AddUrl" to WireMockContainerBuilder to support grpc * fix * fix for windows * wip * fix ! * change some example code
This commit is contained in:
@@ -198,7 +198,7 @@ internal class Program
|
|||||||
var dummyNetwork = new NetworkBuilder()
|
var dummyNetwork = new NetworkBuilder()
|
||||||
.WithName($"Dummy Network for {image ?? "null"}")
|
.WithName($"Dummy Network for {image ?? "null"}")
|
||||||
.WithReuse(true)
|
.WithReuse(true)
|
||||||
.WithCleanUp(true)
|
// .WithCleanUp(true)
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
var builder = new WireMockContainerBuilder()
|
var builder = new WireMockContainerBuilder()
|
||||||
|
|||||||
@@ -21,6 +21,8 @@
|
|||||||
<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" />
|
<Compile Include="..\WireMock.Net\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" />
|
||||||
|
<Compile Include="..\WireMock.Net\Util\PortUtils.cs" Link="Util\PortUtils.cs" />
|
||||||
|
<Compile Include="..\WireMock.Net\Constants\WireMockConstants.cs" Link="Constants\WireMockConstants.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@@ -28,6 +30,10 @@
|
|||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
<PackageReference Include="Nullable" Version="1.3.1">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
||||||
<PackageReference Include="Testcontainers" Version="4.0.0" />
|
<PackageReference Include="Testcontainers" Version="4.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,5 +1,7 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
using Docker.DotNet.Models;
|
using Docker.DotNet.Models;
|
||||||
using DotNet.Testcontainers.Builders;
|
using DotNet.Testcontainers.Builders;
|
||||||
using DotNet.Testcontainers.Configurations;
|
using DotNet.Testcontainers.Configurations;
|
||||||
@@ -24,6 +26,8 @@ public sealed class WireMockConfiguration : ContainerConfiguration
|
|||||||
|
|
||||||
public bool HasBasicAuthentication => !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
|
public bool HasBasicAuthentication => !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
|
||||||
|
|
||||||
|
public List<string> AdditionalUrls { get; private set; } = [];
|
||||||
|
|
||||||
public WireMockConfiguration(string? username = null, string? password = null)
|
public WireMockConfiguration(string? username = null, string? password = null)
|
||||||
{
|
{
|
||||||
Username = username;
|
Username = username;
|
||||||
@@ -70,6 +74,7 @@ public sealed class WireMockConfiguration : ContainerConfiguration
|
|||||||
StaticMappingsPath = BuildConfiguration.Combine(oldValue.StaticMappingsPath, newValue.StaticMappingsPath);
|
StaticMappingsPath = BuildConfiguration.Combine(oldValue.StaticMappingsPath, newValue.StaticMappingsPath);
|
||||||
WatchStaticMappings = BuildConfiguration.Combine(oldValue.WatchStaticMappings, newValue.WatchStaticMappings);
|
WatchStaticMappings = BuildConfiguration.Combine(oldValue.WatchStaticMappings, newValue.WatchStaticMappings);
|
||||||
WatchStaticMappingsInSubdirectories = BuildConfiguration.Combine(oldValue.WatchStaticMappingsInSubdirectories, newValue.WatchStaticMappingsInSubdirectories);
|
WatchStaticMappingsInSubdirectories = BuildConfiguration.Combine(oldValue.WatchStaticMappingsInSubdirectories, newValue.WatchStaticMappingsInSubdirectories);
|
||||||
|
AdditionalUrls = BuildConfiguration.Combine(oldValue.AdditionalUrls.AsEnumerable(), newValue.AdditionalUrls.AsEnumerable()).ToList();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -94,4 +99,15 @@ public sealed class WireMockConfiguration : ContainerConfiguration
|
|||||||
WatchStaticMappingsInSubdirectories = includeSubDirectories;
|
WatchStaticMappingsInSubdirectories = includeSubDirectories;
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// An additional Url on which WireMock listens.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">The url to add.</param>
|
||||||
|
/// <returns><see cref="WireMockConfiguration"/></returns>
|
||||||
|
public WireMockConfiguration WithAdditionalUrl(string url)
|
||||||
|
{
|
||||||
|
AdditionalUrls.Add(url);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,9 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
@@ -30,6 +32,7 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
|
|
||||||
private IWireMockAdminApi? _adminApi;
|
private IWireMockAdminApi? _adminApi;
|
||||||
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
||||||
|
private IDictionary<int, Uri>? _publicUris;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="WireMockContainer" /> class.
|
/// Initializes a new instance of the <see cref="WireMockContainer" /> class.
|
||||||
@@ -48,6 +51,21 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public string GetPublicUrl() => GetPublicUri().ToString();
|
public string GetPublicUrl() => GetPublicUri().ToString();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the public Urls as a dictionary with the internal port as the key.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public IDictionary<int, string> GetPublicUrls() => GetPublicUris().ToDictionary(kvp => kvp.Key, kvp => kvp.Value.ToString());
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the mapped public port for the given container port.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public string GetMappedPublicUrl(int containerPort)
|
||||||
|
{
|
||||||
|
return GetPublicUris()[containerPort].ToString();
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a RestEase Admin client which can be used to call the admin REST endpoint.
|
/// Create a RestEase Admin client which can be used to call the admin REST endpoint.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -121,7 +139,7 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
await ReloadStaticMappingsAsync(target, ct);
|
await ReloadStaticMappingsAsync(target, ct);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reload the static mappings.
|
/// Reload the static mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -198,7 +216,14 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
|
|
||||||
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
private async void FileCreatedChangedOrDeleted(object sender, FileSystemEventArgs args)
|
||||||
{
|
{
|
||||||
await ReloadStaticMappingsAsync(args.FullPath);
|
try
|
||||||
|
{
|
||||||
|
await ReloadStaticMappingsAsync(args.FullPath);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Logger.LogWarning(ex, "Error reloading static mappings from '{FullPath}'.", args.FullPath);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private async Task ReloadStaticMappingsAsync(string path, CancellationToken cancellationToken = default)
|
private async Task ReloadStaticMappingsAsync(string path, CancellationToken cancellationToken = default)
|
||||||
@@ -207,5 +232,27 @@ public sealed class WireMockContainer : DockerContainer
|
|||||||
await ReloadStaticMappingsAsync(cancellationToken);
|
await ReloadStaticMappingsAsync(cancellationToken);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Uri GetPublicUri() => new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(ContainerPort)).Uri;
|
private Uri GetPublicUri() => GetPublicUris()[ContainerPort];
|
||||||
|
|
||||||
|
private IDictionary<int, Uri> GetPublicUris()
|
||||||
|
{
|
||||||
|
if (_publicUris != null)
|
||||||
|
{
|
||||||
|
return _publicUris;
|
||||||
|
}
|
||||||
|
|
||||||
|
_publicUris = _configuration.ExposedPorts.Keys
|
||||||
|
.Select(int.Parse)
|
||||||
|
.ToDictionary(port => port, port => new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(port)).Uri);
|
||||||
|
|
||||||
|
foreach (var url in _configuration.AdditionalUrls)
|
||||||
|
{
|
||||||
|
if (PortUtils.TryExtract(url, out _, out _, out _, out _, out var port))
|
||||||
|
{
|
||||||
|
_publicUris[port] = new UriBuilder(Uri.UriSchemeHttp, Hostname, GetMappedPublicPort(port)).Uri;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return _publicUris;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using Docker.DotNet.Models;
|
using Docker.DotNet.Models;
|
||||||
using DotNet.Testcontainers.Builders;
|
using DotNet.Testcontainers.Builders;
|
||||||
@@ -8,6 +9,7 @@ using DotNet.Testcontainers.Configurations;
|
|||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Net.Testcontainers.Utils;
|
using WireMock.Net.Testcontainers.Utils;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Net.Testcontainers;
|
namespace WireMock.Net.Testcontainers;
|
||||||
|
|
||||||
@@ -132,6 +134,36 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
WithCommand("--WatchStaticMappingsInSubdirectories", includeSubDirectories);
|
WithCommand("--WatchStaticMappingsInSubdirectories", includeSubDirectories);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use Http version 2.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public WireMockContainerBuilder WithHttp2()
|
||||||
|
{
|
||||||
|
return WithCommand("--UseHttp2 true");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Adds another URL to the WireMock container. By default, the WireMock container will listen on <c>http://*:80</c>.
|
||||||
|
///
|
||||||
|
/// This method can be used to also host the WireMock container on another port or protocol (like grpc).
|
||||||
|
/// </summary>
|
||||||
|
/// <example>grpc://*:9090</example>
|
||||||
|
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||||
|
[PublicAPI]
|
||||||
|
public WireMockContainerBuilder AddUrl(string url)
|
||||||
|
{
|
||||||
|
if (!PortUtils.TryExtract(Guard.NotNullOrEmpty(url), out _, out _, out _, out _, out var port))
|
||||||
|
{
|
||||||
|
throw new ArgumentException("The URL is not valid.", nameof(url));
|
||||||
|
}
|
||||||
|
|
||||||
|
DockerResourceConfiguration.WithAdditionalUrl(url);
|
||||||
|
|
||||||
|
return WithPortBinding(port, true);
|
||||||
|
}
|
||||||
|
|
||||||
private WireMockContainerBuilder WithCommand(string param, bool value)
|
private WireMockContainerBuilder WithCommand(string param, bool value)
|
||||||
{
|
{
|
||||||
return !value ? this : WithCommand($"{param} true");
|
return !value ? this : WithCommand($"{param} true");
|
||||||
@@ -172,6 +204,11 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
|||||||
builder = builder.WithBindMount(builder.DockerResourceConfiguration.StaticMappingsPath, ContainerInfoProvider.Info[_imageOS.Value].MappingsPath);
|
builder = builder.WithBindMount(builder.DockerResourceConfiguration.StaticMappingsPath, ContainerInfoProvider.Info[_imageOS.Value].MappingsPath);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (builder.DockerResourceConfiguration.AdditionalUrls.Any())
|
||||||
|
{
|
||||||
|
builder = builder.WithCommand($"--Urls http://*:80 {string.Join(" ", builder.DockerResourceConfiguration.AdditionalUrls)}");
|
||||||
|
}
|
||||||
|
|
||||||
builder.Validate();
|
builder.Validate();
|
||||||
|
|
||||||
return new WireMockContainer(builder.DockerResourceConfiguration);
|
return new WireMockContainer(builder.DockerResourceConfiguration);
|
||||||
|
|||||||
@@ -83,32 +83,6 @@ internal static class PortUtils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// Finds free TCP ports.
|
|
||||||
///// </summary>
|
|
||||||
//public static IReadOnlyList<int> FindFreeTcpPorts(int numPorts)
|
|
||||||
//{
|
|
||||||
// var freePorts = new List<int>();
|
|
||||||
|
|
||||||
// TcpListener? tcpListener = null;
|
|
||||||
// try
|
|
||||||
// {
|
|
||||||
// for (var i = 0; i < numPorts; i++)
|
|
||||||
// {
|
|
||||||
// tcpListener = new TcpListener(IPAddress.Loopback, 0);
|
|
||||||
// tcpListener.Start();
|
|
||||||
|
|
||||||
// freePorts.Add(((IPEndPoint)tcpListener.LocalEndpoint).Port);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// finally
|
|
||||||
// {
|
|
||||||
// tcpListener?.Stop();
|
|
||||||
// }
|
|
||||||
|
|
||||||
// return freePorts;
|
|
||||||
//}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Extract the isHttps, isHttp2, protocol, host and port from a URL.
|
/// Extract the isHttps, isHttp2, protocol, host and port from a URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -118,7 +92,7 @@ internal static class PortUtils
|
|||||||
isHttp2 = false;
|
isHttp2 = false;
|
||||||
protocol = null;
|
protocol = null;
|
||||||
host = null;
|
host = null;
|
||||||
port = default;
|
port = 0;
|
||||||
|
|
||||||
var match = UrlDetailsRegex.Match(url);
|
var match = UrlDetailsRegex.Match(url);
|
||||||
if (match.Success)
|
if (match.Success)
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ using FluentAssertions;
|
|||||||
using Google.Protobuf.WellKnownTypes;
|
using Google.Protobuf.WellKnownTypes;
|
||||||
using Greet;
|
using Greet;
|
||||||
using Grpc.Net.Client;
|
using Grpc.Net.Client;
|
||||||
using NarrowIntegrationTest.Lookup;
|
using ExampleIntegrationTest.Lookup;
|
||||||
using WireMock.Constants;
|
using WireMock.Constants;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
@@ -668,7 +668,7 @@ message Other {
|
|||||||
.RespondWith(Response.Create()
|
.RespondWith(Response.Create()
|
||||||
.WithHeader("Content-Type", "application/grpc")
|
.WithHeader("Content-Type", "application/grpc")
|
||||||
.WithTrailingHeader("grpc-status", "0")
|
.WithTrailingHeader("grpc-status", "0")
|
||||||
.WithBodyAsProtoBuf(definition, "NarrowIntegrationTest.Lookup.GetVersionResponse",
|
.WithBodyAsProtoBuf(definition, "ExampleIntegrationTest.Lookup.GetVersionResponse",
|
||||||
new GetVersionResponse
|
new GetVersionResponse
|
||||||
{
|
{
|
||||||
Version = version,
|
Version = version,
|
||||||
@@ -677,9 +677,9 @@ message Other {
|
|||||||
Seconds = seconds,
|
Seconds = seconds,
|
||||||
Nanos = nanos
|
Nanos = nanos
|
||||||
},
|
},
|
||||||
Client = new NarrowIntegrationTest.Lookup.Client
|
Client = new ExampleIntegrationTest.Lookup.Client
|
||||||
{
|
{
|
||||||
ClientName = NarrowIntegrationTest.Lookup.Client.Types.Clients.BillingCenter,
|
ClientName = ExampleIntegrationTest.Lookup.Client.Types.Clients.Test,
|
||||||
CorrelationId = correlationId
|
CorrelationId = correlationId
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -695,23 +695,34 @@ message Other {
|
|||||||
// Assert
|
// Assert
|
||||||
reply.Version.Should().Be(version);
|
reply.Version.Should().Be(version);
|
||||||
reply.DateHired.Should().Be(new Timestamp { Seconds = seconds, Nanos = nanos });
|
reply.DateHired.Should().Be(new Timestamp { Seconds = seconds, Nanos = nanos });
|
||||||
reply.Client.ClientName.Should().Be(NarrowIntegrationTest.Lookup.Client.Types.Clients.BillingCenter);
|
reply.Client.ClientName.Should().Be(ExampleIntegrationTest.Lookup.Client.Types.Clients.Test);
|
||||||
reply.Client.CorrelationId.Should().Be(correlationId);
|
reply.Client.CorrelationId.Should().Be(correlationId);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WireMockServer_WithBodyAsProtoBuf_ServerProtoDefinitionFromJson_UsingGrpcGeneratedClient()
|
public async Task WireMockServer_WithBodyAsProtoBuf_FromJson_UsingGrpcGeneratedClient()
|
||||||
{
|
{
|
||||||
var server = Given_When_ServerStartedUsingHttp2();
|
var server = Given_When_ServerStarted_And_RunningOnHttpAndGrpc();
|
||||||
Given_ProtoDefinition_IsAddedOnServerLevel(server);
|
await Given_When_ProtoBufMappingIsAddedViaAdminInterfaceAsync(server, "protobuf-mapping-1.json");
|
||||||
await Given_When_ProtoBufMappingIsAddedViaAdminInterfaceAsync(server);
|
|
||||||
|
|
||||||
var reply = await When_GrpcClient_Calls_SayHelloAsync(server.Urls[1]);
|
var reply = await When_GrpcClient_Calls_SayHelloAsync(server.Urls[1]);
|
||||||
|
|
||||||
Then_ReplyMessage_Should_BeCorrect(reply);
|
Then_ReplyMessage_Should_BeCorrect(reply);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static WireMockServer Given_When_ServerStartedUsingHttp2()
|
[Fact]
|
||||||
|
public async Task WireMockServer_WithBodyAsProtoBuf_ServerProtoDefinitionFromJson_UsingGrpcGeneratedClient()
|
||||||
|
{
|
||||||
|
var server = Given_When_ServerStarted_And_RunningOnHttpAndGrpc();
|
||||||
|
Given_ProtoDefinition_IsAddedOnServerLevel(server);
|
||||||
|
await Given_When_ProtoBufMappingIsAddedViaAdminInterfaceAsync(server, "protobuf-mapping-3.json");
|
||||||
|
|
||||||
|
var reply = await When_GrpcClient_Calls_SayHelloAsync(server.Urls[1]);
|
||||||
|
|
||||||
|
Then_ReplyMessage_Should_BeCorrect(reply);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static WireMockServer Given_When_ServerStarted_And_RunningOnHttpAndGrpc()
|
||||||
{
|
{
|
||||||
var ports = PortUtils.FindFreeTcpPorts(2);
|
var ports = PortUtils.FindFreeTcpPorts(2);
|
||||||
|
|
||||||
@@ -728,9 +739,9 @@ message Other {
|
|||||||
server.AddProtoDefinition("my-greeter", ReadProtoFile("greet.proto"));
|
server.AddProtoDefinition("my-greeter", ReadProtoFile("greet.proto"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task Given_When_ProtoBufMappingIsAddedViaAdminInterfaceAsync(WireMockServer server)
|
private static async Task Given_When_ProtoBufMappingIsAddedViaAdminInterfaceAsync(WireMockServer server, string filename)
|
||||||
{
|
{
|
||||||
var mappingsJson = ReadMappingFile("protobuf-mapping-3.json");
|
var mappingsJson = ReadMappingFile(filename);
|
||||||
|
|
||||||
using var httpClient = server.CreateClient();
|
using var httpClient = server.CreateClient();
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
syntax = "proto3";
|
syntax = "proto3";
|
||||||
|
|
||||||
option csharp_namespace = "NarrowIntegrationTest.Lookup";
|
option csharp_namespace = "ExampleIntegrationTest.Lookup";
|
||||||
|
|
||||||
import "google/protobuf/timestamp.proto";
|
import "google/protobuf/timestamp.proto";
|
||||||
|
|
||||||
@@ -24,17 +24,8 @@ message Client {
|
|||||||
string CorrelationId = 1;
|
string CorrelationId = 1;
|
||||||
enum Clients {
|
enum Clients {
|
||||||
Unknown = 0;
|
Unknown = 0;
|
||||||
QMS = 1;
|
Other = 1;
|
||||||
BillingCenter = 2;
|
Test = 2;
|
||||||
PAS = 3;
|
|
||||||
Payroll = 4;
|
|
||||||
Portal = 5;
|
|
||||||
SFO = 6;
|
|
||||||
QuoteAndBind = 7;
|
|
||||||
LegacyConversion = 8;
|
|
||||||
BindNow = 9;
|
|
||||||
PaymentPortal = 10 ;
|
|
||||||
PricingEngine = 11;
|
|
||||||
}
|
}
|
||||||
Clients ClientName = 2;
|
Clients ClientName = 2;
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,186 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
#if NET6_0_OR_GREATER
|
||||||
|
using System;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using FluentAssertions;
|
||||||
|
using FluentAssertions.Execution;
|
||||||
|
using Greet;
|
||||||
|
using Grpc.Net.Client;
|
||||||
|
using WireMock.Constants;
|
||||||
|
using WireMock.Net.Testcontainers;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Tests.Testcontainers;
|
||||||
|
|
||||||
|
public partial class TestcontainersTests
|
||||||
|
{
|
||||||
|
[Fact]
|
||||||
|
public async Task WireMockContainer_Build_Grpc_TestPortsAndUrls1()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var adminUsername = $"username_{Guid.NewGuid()}";
|
||||||
|
var adminPassword = $"password_{Guid.NewGuid()}";
|
||||||
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithAutoRemove(true)
|
||||||
|
.WithCleanUp(true)
|
||||||
|
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
|
||||||
|
.WithCommand("--UseHttp2")
|
||||||
|
.WithCommand("--Urls", "http://*:80 grpc://*:9090")
|
||||||
|
.WithPortBinding(9090, true)
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await wireMockContainer.StartAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
using (new AssertionScope())
|
||||||
|
{
|
||||||
|
var logs = await wireMockContainer.GetLogsAsync(DateTime.MinValue);
|
||||||
|
logs.Should().NotBeNull();
|
||||||
|
|
||||||
|
var url = wireMockContainer.GetPublicUrl();
|
||||||
|
url.Should().NotBeNullOrWhiteSpace();
|
||||||
|
|
||||||
|
var urls = wireMockContainer.GetPublicUrls();
|
||||||
|
urls.Should().HaveCount(2);
|
||||||
|
|
||||||
|
var httpPort = wireMockContainer.GetMappedPublicPort(80);
|
||||||
|
httpPort.Should().BeGreaterThan(0);
|
||||||
|
|
||||||
|
var httpUrl = wireMockContainer.GetMappedPublicUrl(80);
|
||||||
|
httpUrl.Should().StartWith("http://");
|
||||||
|
|
||||||
|
var grpcPort = wireMockContainer.GetMappedPublicPort(9090);
|
||||||
|
grpcPort.Should().BeGreaterThan(0);
|
||||||
|
|
||||||
|
var grpcUrl = wireMockContainer.GetMappedPublicUrl(80);
|
||||||
|
grpcUrl.Should().StartWith("http://");
|
||||||
|
|
||||||
|
var adminClient = wireMockContainer.CreateWireMockAdminClient();
|
||||||
|
|
||||||
|
var settings = await adminClient.GetSettingsAsync();
|
||||||
|
settings.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
await wireMockContainer.StopAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task WireMockContainer_Build_Grpc_TestPortsAndUrls2()
|
||||||
|
{
|
||||||
|
// Act
|
||||||
|
var adminUsername = $"username_{Guid.NewGuid()}";
|
||||||
|
var adminPassword = $"password_{Guid.NewGuid()}";
|
||||||
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithAutoRemove(true)
|
||||||
|
.WithCleanUp(true)
|
||||||
|
.WithAdminUserNameAndPassword(adminUsername, adminPassword)
|
||||||
|
.AddUrl("http://*:8080")
|
||||||
|
.AddUrl("grpc://*:9090")
|
||||||
|
.AddUrl("grpc://*:9091")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
await wireMockContainer.StartAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
using (new AssertionScope())
|
||||||
|
{
|
||||||
|
var logs = await wireMockContainer.GetLogsAsync(DateTime.MinValue);
|
||||||
|
logs.Should().NotBeNull();
|
||||||
|
|
||||||
|
var url = wireMockContainer.GetPublicUrl();
|
||||||
|
url.Should().NotBeNullOrWhiteSpace();
|
||||||
|
|
||||||
|
var urls = wireMockContainer.GetPublicUrls();
|
||||||
|
urls.Should().HaveCount(4);
|
||||||
|
|
||||||
|
foreach (var internalPort in new[] { 80, 8080, 9090, 9091 })
|
||||||
|
{
|
||||||
|
var publicPort = wireMockContainer.GetMappedPublicPort(internalPort);
|
||||||
|
publicPort.Should().BeGreaterThan(0);
|
||||||
|
|
||||||
|
var publicUrl = wireMockContainer.GetMappedPublicUrl(internalPort);
|
||||||
|
publicUrl.Should().StartWith("http://");
|
||||||
|
}
|
||||||
|
|
||||||
|
var adminClient = wireMockContainer.CreateWireMockAdminClient();
|
||||||
|
|
||||||
|
var settings = await adminClient.GetSettingsAsync();
|
||||||
|
settings.Should().NotBeNull();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
await wireMockContainer.StopAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public async Task WireMockContainer_Build_Grpc_ProtoDefinitionFromJson_UsingGrpcGeneratedClient()
|
||||||
|
{
|
||||||
|
var wireMockContainer = await Given_WireMockContainerIsStartedForHttpAndGrpc();
|
||||||
|
|
||||||
|
await Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(wireMockContainer);
|
||||||
|
|
||||||
|
var reply = await When_GrpcClient_Calls_SayHelloAsync(wireMockContainer);
|
||||||
|
|
||||||
|
Then_ReplyMessage_Should_BeCorrect(reply);
|
||||||
|
|
||||||
|
await wireMockContainer.StopAsync();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<WireMockContainer> Given_WireMockContainerIsStartedForHttpAndGrpc()
|
||||||
|
{
|
||||||
|
var wireMockContainer = new WireMockContainerBuilder()
|
||||||
|
.WithAutoRemove(true)
|
||||||
|
.WithCleanUp(true)
|
||||||
|
.AddUrl("grpc://*:9090")
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
await wireMockContainer.StartAsync();
|
||||||
|
|
||||||
|
return wireMockContainer;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task Given_ProtoBufMappingIsAddedViaAdminInterfaceAsync(WireMockContainer wireMockContainer)
|
||||||
|
{
|
||||||
|
var mappingsJson = ReadMappingFile("protobuf-mapping-1.json");
|
||||||
|
|
||||||
|
using var httpClient = wireMockContainer.CreateClient();
|
||||||
|
|
||||||
|
var result = await httpClient.PostAsync("/__admin/mappings", new StringContent(mappingsJson, Encoding.UTF8, WireMockConstants.ContentTypeJson));
|
||||||
|
result.EnsureSuccessStatusCode();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task<HelloReply> When_GrpcClient_Calls_SayHelloAsync(WireMockContainer wireMockContainer)
|
||||||
|
{
|
||||||
|
var address = wireMockContainer.GetPublicUrls()[9090];
|
||||||
|
var channel = GrpcChannel.ForAddress(address);
|
||||||
|
|
||||||
|
var client = new Greeter.GreeterClient(channel);
|
||||||
|
|
||||||
|
return await client.SayHelloAsync(new HelloRequest { Name = "stef" });
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Then_ReplyMessage_Should_BeCorrect(HelloReply reply)
|
||||||
|
{
|
||||||
|
reply.Message.Should().Be("hello stef POST");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ReadMappingFile(string filename)
|
||||||
|
{
|
||||||
|
return File.ReadAllText(Path.Combine(Directory.GetCurrentDirectory(), "__admin", "mappings", filename));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -8,15 +8,16 @@ using DotNet.Testcontainers.Builders;
|
|||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using FluentAssertions.Execution;
|
using FluentAssertions.Execution;
|
||||||
using WireMock.Net.Testcontainers;
|
using WireMock.Net.Testcontainers;
|
||||||
|
using WireMock.Net.Testcontainers.Utils;
|
||||||
using WireMock.Net.Tests.Facts;
|
using WireMock.Net.Tests.Facts;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
|
|
||||||
namespace WireMock.Net.Tests.Testcontainers;
|
namespace WireMock.Net.Tests.Testcontainers;
|
||||||
|
|
||||||
public class TestcontainersTests
|
public partial class TestcontainersTests
|
||||||
{
|
{
|
||||||
[Fact]
|
[Fact]
|
||||||
public async Task WireMockContainer_Build_WithNoImage_And_StartAsync_and_StopAsync()
|
public async Task WireMockContainer_Build_And_StartAsync_and_StopAsync()
|
||||||
{
|
{
|
||||||
// Act
|
// Act
|
||||||
var adminUsername = $"username_{Guid.NewGuid()}";
|
var adminUsername = $"username_{Guid.NewGuid()}";
|
||||||
@@ -32,7 +33,7 @@ public class TestcontainersTests
|
|||||||
|
|
||||||
// https://github.com/testcontainers/testcontainers-dotnet/issues/1322
|
// https://github.com/testcontainers/testcontainers-dotnet/issues/1322
|
||||||
[RunOnDockerPlatformFact("Linux")]
|
[RunOnDockerPlatformFact("Linux")]
|
||||||
public async Task WireMockContainer_Build_WithNoImageAndNetwork_And_StartAsync_and_StopAsync()
|
public async Task WireMockContainer_Build_WithNetwork_And_StartAsync_and_StopAsync()
|
||||||
{
|
{
|
||||||
// Act
|
// Act
|
||||||
var dummyNetwork = new NetworkBuilder()
|
var dummyNetwork = new NetworkBuilder()
|
||||||
@@ -61,7 +62,8 @@ public class TestcontainersTests
|
|||||||
.WithCleanUp(true)
|
.WithCleanUp(true)
|
||||||
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
|
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
|
||||||
|
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
var imageOS = await TestcontainersUtils.GetImageOSAsync.Value;
|
||||||
|
if (imageOS == OSPlatform.Windows)
|
||||||
{
|
{
|
||||||
wireMockContainerBuilder = wireMockContainerBuilder.WithWindowsImage();
|
wireMockContainerBuilder = wireMockContainerBuilder.WithWindowsImage();
|
||||||
}
|
}
|
||||||
@@ -86,7 +88,8 @@ public class TestcontainersTests
|
|||||||
.WithCleanUp(true)
|
.WithCleanUp(true)
|
||||||
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
|
.WithAdminUserNameAndPassword(adminUsername, adminPassword);
|
||||||
|
|
||||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
var imageOS = await TestcontainersUtils.GetImageOSAsync.Value;
|
||||||
|
if (imageOS == OSPlatform.Windows)
|
||||||
{
|
{
|
||||||
wireMockContainerBuilder = wireMockContainerBuilder.WithImage("sheyenrath/wiremock.net-windows");
|
wireMockContainerBuilder = wireMockContainerBuilder.WithImage("sheyenrath/wiremock.net-windows");
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
},
|
},
|
||||||
"Response": {
|
"Response": {
|
||||||
"BodyAsJson": {
|
"BodyAsJson": {
|
||||||
"message": "hello {{request.BodyAsJson.name}}"
|
"message": "hello {{request.BodyAsJson.name}} {{request.method}}"
|
||||||
},
|
},
|
||||||
"UseTransformer": true,
|
"UseTransformer": true,
|
||||||
"TransformerType": "Handlebars",
|
"TransformerType": "Handlebars",
|
||||||
|
|||||||
Reference in New Issue
Block a user