diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 040d192b..12d8d7f4 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -22,6 +22,9 @@ jobs:
- name: 'WireMock.Net.Tests'
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
+ - name: 'WireMock.Net.Tests.UsingNuGet'
+ run: dotnet test './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj' -c Release
+
- name: 'WireMock.Net.TUnitTests'
run: dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
@@ -46,6 +49,9 @@ jobs:
- name: 'WireMock.Net.Tests'
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
+ - name: 'WireMock.Net.Tests.UsingNuGet'
+ run: dotnet test './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj' -c Release
+
- name: 'WireMock.Net.TUnitTests'
run: dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln
index 05339c42..db8ff663 100644
--- a/WireMock.Net Solution.sln
+++ b/WireMock.Net Solution.sln
@@ -132,6 +132,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Shared", "src\
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Minimal", "src\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj", "{BFEF8990-65B3-4274-310F-7355F0B84035}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.ConsoleApp.UsingNuGet", "examples\WireMock.Net.ConsoleApp.UsingNuGet\WireMock.Net.ConsoleApp.UsingNuGet.csproj", "{1F80A6E6-D146-4E40-9EA8-49DB8494239F}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Tests.UsingNuGet", "test\WireMock.Net.Tests.UsingNuGet\WireMock.Net.Tests.UsingNuGet.csproj", "{BBA332C6-28A9-42E7-9C4D-A0816E52A198}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -314,6 +318,14 @@ Global
{BFEF8990-65B3-4274-310F-7355F0B84035}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|Any CPU.Build.0 = Release|Any CPU
+ {1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|Any CPU.Build.0 = Release|Any CPU
+ {BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -365,6 +377,8 @@ Global
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{D3804228-91F4-4502-9595-39584E5A0177} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{BFEF8990-65B3-4274-310F-7355F0B84035} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
+ {1F80A6E6-D146-4E40-9EA8-49DB8494239F} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
+ {BBA332C6-28A9-42E7-9C4D-A0816E52A198} = {0BB8B634-407A-4610-A91F-11586990767A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
diff --git a/azure-pipelines-ci.yml b/azure-pipelines-ci.yml
index a20a72d0..35d671b7 100644
--- a/azure-pipelines-ci.yml
+++ b/azure-pipelines-ci.yml
@@ -109,6 +109,13 @@ jobs:
packageType: 'sdk'
version: '8.0.x'
+ - task: DotNetCoreCLI@2
+ displayName: 'WireMock.Net.Tests.UsingNuGet'
+ inputs:
+ command: 'test'
+ projects: './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj'
+ arguments: '--configuration Release'
+
- task: DotNetCoreCLI@2
displayName: 'WireMock.Net.Tests with Coverage'
inputs:
diff --git a/examples/WireMock.Net.ConsoleApp.UsingNuGet/Program.cs b/examples/WireMock.Net.ConsoleApp.UsingNuGet/Program.cs
new file mode 100644
index 00000000..51217211
--- /dev/null
+++ b/examples/WireMock.Net.ConsoleApp.UsingNuGet/Program.cs
@@ -0,0 +1,88 @@
+// Copyright © WireMock.Net
+
+using System.Net.Http.Headers;
+using System.Text;
+using WireMock.Matchers;
+using WireMock.RequestBuilders;
+using WireMock.ResponseBuilders;
+using WireMock.Server;
+
+Directory.SetCurrentDirectory(Path.GetTempPath());
+
+using var server = WireMockServer.Start();
+
+var textPlainContent = "This is some plain text";
+var textPlainContentType = "text/plain";
+var textPlainContentTypeMatcher = new ContentTypeMatcher(textPlainContentType);
+var textPlainContentMatcher = new ExactMatcher(textPlainContent);
+var textPlainMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textPlainContentTypeMatcher, null, null, textPlainContentMatcher);
+
+var textJson = "{ \"Key\" : \"Value\" }";
+var textJsonContentType = "text/json";
+var textJsonContentTypeMatcher = new ContentTypeMatcher(textJsonContentType);
+var textJsonContentMatcher = new JsonMatcher(new { Key = "Value" }, true);
+var jsonMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textJsonContentTypeMatcher, null, null, textJsonContentMatcher);
+
+var imagePngBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjlAAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC");
+var imagePngContentMatcher = new ExactObjectMatcher(imagePngBytes);
+var imagePngMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, null, null, null, imagePngContentMatcher);
+
+var matchers = new IMatcher[]
+{
+ textPlainMatcher,
+ jsonMatcher,
+ imagePngMatcher
+};
+
+server
+ .Given(Request.Create()
+ .UsingPost()
+ .WithPath("/multipart")
+ .WithMultiPart(matchers)
+ )
+ .RespondWith(Response.Create()
+ .WithBodyAsJson(new
+ {
+ Method = "{{request.Method}}",
+ BodyAsMimeMessage = "{{request.BodyAsMimeMessage.TextBody}}"
+ })
+ .WithTransformer()
+ );
+
+server
+ .Given(Request.Create()
+ .UsingPost()
+ .WithPath("/multipart2")
+ .WithMultiPart(matchers)
+ )
+ .RespondWith(Response.Create()
+ .WithBody(request =>
+ {
+ if (request.BodyAsMimeMessage == null)
+ {
+ throw new InvalidProgramException("Not expected");
+ }
+ return "OK";
+ })
+ .WithTransformer()
+ );
+
+var formDataContent = new MultipartFormDataContent
+{
+ { new StringContent(textPlainContent, Encoding.UTF8, textPlainContentType), "text" },
+ { new StringContent(textJson, Encoding.UTF8, textJsonContentType), "json" }
+};
+
+var fileContent = new ByteArrayContent(imagePngBytes);
+fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
+formDataContent.Add(fileContent, "somefile", "image.png");
+
+var client = server.CreateClient();
+
+var response = await client.PostAsync("/multipart", formDataContent);
+var content = await response.Content.ReadAsStringAsync();
+Console.WriteLine(content);
+
+var response2 = await client.PostAsync("/multipart2", formDataContent);
+var content2 = await response2.Content.ReadAsStringAsync();
+Console.WriteLine(content2);
\ No newline at end of file
diff --git a/examples/WireMock.Net.ConsoleApp.UsingNuGet/WireMock.Net.ConsoleApp.UsingNuGet.csproj b/examples/WireMock.Net.ConsoleApp.UsingNuGet/WireMock.Net.ConsoleApp.UsingNuGet.csproj
new file mode 100644
index 00000000..ba3f5902
--- /dev/null
+++ b/examples/WireMock.Net.ConsoleApp.UsingNuGet/WireMock.Net.ConsoleApp.UsingNuGet.csproj
@@ -0,0 +1,18 @@
+
+
+
+ Exe
+ net8.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/WireMock.Net.MimePart/Util/MimeKitUtils.cs b/src/WireMock.Net.MimePart/Util/MimeKitUtils.cs
index bd05f1e0..e0bd93ca 100644
--- a/src/WireMock.Net.MimePart/Util/MimeKitUtils.cs
+++ b/src/WireMock.Net.MimePart/Util/MimeKitUtils.cs
@@ -28,7 +28,7 @@ internal class MimeKitUtils : IMimeKitUtils
if (requestMessage.BodyData != null &&
requestMessage.Headers?.TryGetValue(HttpKnownHeaderNames.ContentType, out var contentTypeHeader) == true &&
- StartsWithMultiPart(contentTypeHeader) // Only parse when "multipart/mixed"
+ StartsWithMultiPart(contentTypeHeader)
)
{
var bytes = requestMessage.BodyData?.DetectedBodyType switch
diff --git a/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj b/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj
index edbfad31..26251d62 100644
--- a/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj
+++ b/src/WireMock.Net.MimePart/WireMock.Net.MimePart.csproj
@@ -36,9 +36,9 @@
-
- all
- runtime; build; native; contentfiles; analyzers; buildtransitive
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/src/WireMock.Net.Minimal/Util/TypeLoader.cs b/src/WireMock.Net.Minimal/Util/TypeLoader.cs
index 35ac0272..60ba7fdd 100644
--- a/src/WireMock.Net.Minimal/Util/TypeLoader.cs
+++ b/src/WireMock.Net.Minimal/Util/TypeLoader.cs
@@ -51,7 +51,7 @@ internal static class TypeLoader
{
var key = typeof(TInterface).FullName!;
- var pluginType = Assemblies.GetOrAdd(key, _ =>
+ return Assemblies.GetOrAdd(key, _ =>
{
if (TryFindTypeInDlls(null, out var foundType))
{
@@ -60,7 +60,6 @@ internal static class TypeLoader
throw new DllNotFoundException($"No dll found which implements interface '{key}'.");
});
- return pluginType;
}
private static Type GetPluginTypeByFullName(string implementationTypeFullName) where TInterface : class
@@ -68,7 +67,7 @@ internal static class TypeLoader
var @interface = typeof(TInterface).FullName;
var key = $"{@interface}_{implementationTypeFullName}";
- var pluginType = Assemblies.GetOrAdd(key, _ =>
+ return Assemblies.GetOrAdd(key, _ =>
{
if (TryFindTypeInDlls(implementationTypeFullName, out var foundType))
{
@@ -77,28 +76,40 @@ internal static class TypeLoader
throw new DllNotFoundException($"No dll found which implements Interface '{@interface}' and has FullName '{implementationTypeFullName}'.");
});
- return pluginType;
}
private static bool TryFindTypeInDlls(string? implementationTypeFullName, [NotNullWhen(true)] out Type? pluginType) where TInterface : class
{
- foreach (var file in Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll"))
+#if NETSTANDARD1_3
+ var directoriesToSearch = new[] { AppContext.BaseDirectory };
+#else
+ var processDirectory = Path.GetDirectoryName(System.Diagnostics.Process.GetCurrentProcess().MainModule?.FileName);
+ var assemblyDirectory = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
+ var directoriesToSearch = new[] { processDirectory, assemblyDirectory }
+ .Where(d => !string.IsNullOrEmpty(d))
+ .Distinct()
+ .ToArray();
+#endif
+ foreach (var directory in directoriesToSearch)
{
- try
+ foreach (var file in Directory.GetFiles(directory!, "*.dll"))
{
- var assembly = Assembly.Load(new AssemblyName
+ try
{
- Name = Path.GetFileNameWithoutExtension(file)
- });
+ var assembly = Assembly.Load(new AssemblyName
+ {
+ Name = Path.GetFileNameWithoutExtension(file)
+ });
- if (TryGetImplementationTypeByInterfaceAndOptionalFullName(assembly, implementationTypeFullName, out pluginType))
- {
- return true;
+ if (TryGetImplementationTypeByInterfaceAndOptionalFullName(assembly, implementationTypeFullName, out pluginType))
+ {
+ return true;
+ }
+ }
+ catch
+ {
+ // no-op: just try next .dll
}
- }
- catch
- {
- // no-op: just try next .dll
}
}
diff --git a/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj
index e2320ff0..bfd7f6c8 100644
--- a/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj
+++ b/src/WireMock.Net.Minimal/WireMock.Net.Minimal.csproj
@@ -65,7 +65,7 @@
-
+
all
runtime; build; native; contentfiles; analyzers; buildtransitive
diff --git a/test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj b/test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj
new file mode 100644
index 00000000..4facbda3
--- /dev/null
+++ b/test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj
@@ -0,0 +1,39 @@
+
+
+
+ net8.0
+ enable
+ enable
+
+ false
+ true
+
+
+
+ $(DefineConstants);GRAPHQL;MIMEKIT;PROTOBUF
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+ all
+ runtime; build; native; contentfiles; analyzers; buildtransitive
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/WireMock.Net.Tests.UsingNuGet/WireMockServerTests.WithMultiPart.cs b/test/WireMock.Net.Tests.UsingNuGet/WireMockServerTests.WithMultiPart.cs
new file mode 100644
index 00000000..4237df8e
--- /dev/null
+++ b/test/WireMock.Net.Tests.UsingNuGet/WireMockServerTests.WithMultiPart.cs
@@ -0,0 +1,103 @@
+// Copyright © WireMock.Net
+
+using System.Net;
+using System.Net.Http.Headers;
+using System.Text;
+using AwesomeAssertions;
+using WireMock.Matchers;
+using WireMock.RequestBuilders;
+using WireMock.ResponseBuilders;
+using WireMock.Server;
+
+// ReSharper disable once CheckNamespace
+namespace WireMock.Net.Tests;
+
+public partial class WireMockServerTests
+{
+ [Fact]
+ public async Task WireMockServer_WithMultiPartBody_Using_MimePartMatchers()
+ {
+ // Arrange
+ using var server = WireMockServer.Start();
+
+ var textPlainContent = "This is some plain text";
+ var textPlainContentType = "text/plain";
+ var textPlainContentTypeMatcher = new ContentTypeMatcher(textPlainContentType);
+ var textPlainContentMatcher = new ExactMatcher(textPlainContent);
+ var textPlainMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textPlainContentTypeMatcher, null, null, textPlainContentMatcher);
+
+ var textJson = "{ \"Key\" : \"Value\" }";
+ var textJsonContentType = "text/json";
+ var textJsonContentTypeMatcher = new ContentTypeMatcher(textJsonContentType);
+ var textJsonContentMatcher = new JsonMatcher(new { Key = "Value" }, true);
+ var jsonMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textJsonContentTypeMatcher, null, null, textJsonContentMatcher);
+
+ var imagePngBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjlAAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC");
+ var imagePngContentMatcher = new ExactObjectMatcher(imagePngBytes);
+ var imagePngMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, null, null, null, imagePngContentMatcher);
+
+ var matchers = new IMatcher[]
+ {
+ textPlainMatcher,
+ jsonMatcher,
+ imagePngMatcher
+ };
+
+ server
+ .Given(Request.Create()
+ .UsingPost()
+ .WithPath("/multipart")
+ .WithMultiPart(matchers)
+ )
+ .RespondWith(Response.Create()
+ .WithBody("{{request.Method}};{{request.BodyAsMimeMessage.TextBody}}")
+ .WithTransformer()
+ );
+
+ server
+ .Given(Request.Create()
+ .UsingPost()
+ .WithPath("/multipart2")
+ .WithMultiPart(matchers)
+ )
+ .RespondWith(Response.Create()
+ .WithBody(request =>
+ {
+ if (request.BodyAsMimeMessage == null)
+ {
+ throw new InvalidProgramException("Not expected");
+ }
+ return "OK";
+ })
+ .WithTransformer()
+ );
+
+ var formDataContent = new MultipartFormDataContent
+ {
+ { new StringContent(textPlainContent, Encoding.UTF8, textPlainContentType), "text" },
+ { new StringContent(textJson, Encoding.UTF8, textJsonContentType), "json" }
+ };
+
+ var fileContent = new ByteArrayContent(imagePngBytes);
+ fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
+ formDataContent.Add(fileContent, "somefile", "image.png");
+
+ var client = server.CreateClient();
+
+ // Act 1
+ var response1 = await client.PostAsync("/multipart", formDataContent);
+
+ // Assert 1
+ response1.StatusCode.Should().Be(HttpStatusCode.OK);
+ var content1 = await response1.Content.ReadAsStringAsync();
+ content1.Should().Be("POST;This is some plain text");
+
+ // Act 2
+ var response2 = await client.PostAsync("/multipart2", formDataContent);
+
+ // Assert 1
+ response2.StatusCode.Should().Be(HttpStatusCode.OK);
+ var content2 = await response2.Content.ReadAsStringAsync();
+ content2.Should().Be("OK");
+ }
+}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/Util/TypeLoaderTests.cs b/test/WireMock.Net.Tests/Util/TypeLoaderTests.cs
index 7d1accb7..6b591f6e 100644
--- a/test/WireMock.Net.Tests/Util/TypeLoaderTests.cs
+++ b/test/WireMock.Net.Tests/Util/TypeLoaderTests.cs
@@ -1,6 +1,7 @@
// Copyright © WireMock.Net
using System;
+using System.IO;
using AnyOfTypes;
using FluentAssertions;
using WireMock.Matchers;
@@ -57,12 +58,22 @@ public class TypeLoaderTests
[Fact]
public void LoadNewInstance()
{
- // Act
- AnyOf pattern = "x";
- var result = TypeLoader.LoadNewInstance(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, pattern);
+ var current = Directory.GetCurrentDirectory();
+ try
+ {
+ Directory.SetCurrentDirectory(Path.GetTempPath());
- // Assert
- result.Should().NotBeNull();
+ // Act
+ AnyOf pattern = "x";
+ var result = TypeLoader.LoadNewInstance(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, pattern);
+
+ // Assert
+ result.Should().NotBeNull();
+ }
+ finally
+ {
+ Directory.SetCurrentDirectory(current);
+ }
}
[Fact]