diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln
index 6171262f..ae7957fe 100644
--- a/WireMock.Net Solution.sln
+++ b/WireMock.Net Solution.sln
@@ -69,6 +69,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.OpenApiParser"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.OpenApiParser.ConsoleApp", "examples\WireMock.Net.OpenApiParser.ConsoleApp\WireMock.Net.OpenApiParser.ConsoleApp.csproj", "{5C09FB93-1535-4F92-AF26-21E8A061EE4A}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.FluentAssertions", "src\WireMock.Net.FluentAssertions\WireMock.Net.FluentAssertions.csproj", "{2C837E73-5EDD-43AD-B65A-194E4A3AD9FE}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -167,6 +169,10 @@ Global
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5C09FB93-1535-4F92-AF26-21E8A061EE4A}.Release|Any CPU.Build.0 = Release|Any CPU
+ {2C837E73-5EDD-43AD-B65A-194E4A3AD9FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {2C837E73-5EDD-43AD-B65A-194E4A3AD9FE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {2C837E73-5EDD-43AD-B65A-194E4A3AD9FE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {2C837E73-5EDD-43AD-B65A-194E4A3AD9FE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -195,6 +201,7 @@ Global
{02082E34-DEF2-47D0-AF0B-3326FAA908CE} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{D3804228-91F4-4502-9595-39584E5AADAD} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{5C09FB93-1535-4F92-AF26-21E8A061EE4A} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
+ {2C837E73-5EDD-43AD-B65A-194E4A3AD9FE} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
diff --git a/src/WireMock.Net.Abstractions/Admin/Requests/LogEntryModel.cs b/src/WireMock.Net.Abstractions/Admin/Requests/LogEntryModel.cs
index 8a97f0fd..8c6e6f5f 100644
--- a/src/WireMock.Net.Abstractions/Admin/Requests/LogEntryModel.cs
+++ b/src/WireMock.Net.Abstractions/Admin/Requests/LogEntryModel.cs
@@ -36,5 +36,20 @@ namespace WireMock.Admin.Requests
/// The request match result.
///
public LogRequestMatchModel RequestMatchResult { get; set; }
+
+ ///
+ /// The partial mapping unique identifier.
+ ///
+ public Guid? PartialMappingGuid { get; set; }
+
+ ///
+ /// The partial mapping unique title.
+ ///
+ public string PartialMappingTitle { get; set; }
+
+ ///
+ /// The partial request match result.
+ ///
+ public LogRequestMatchModel PartialRequestMatchResult { get; set; }
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net.FluentAssertions/Assertions/WireMockANumberOfCallsAssertions.cs b/src/WireMock.Net.FluentAssertions/Assertions/WireMockANumberOfCallsAssertions.cs
new file mode 100644
index 00000000..aff156e4
--- /dev/null
+++ b/src/WireMock.Net.FluentAssertions/Assertions/WireMockANumberOfCallsAssertions.cs
@@ -0,0 +1,22 @@
+using WireMock.Server;
+
+// ReSharper disable once CheckNamespace
+namespace WireMock.FluentAssertions
+{
+ public class WireMockANumberOfCallsAssertions
+ {
+ private readonly WireMockServer _server;
+ private readonly int _callsCount;
+
+ public WireMockANumberOfCallsAssertions(WireMockServer server, int callsCount)
+ {
+ _server = server;
+ _callsCount = callsCount;
+ }
+
+ public WireMockAssertions Calls()
+ {
+ return new WireMockAssertions(_server, _callsCount);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.cs b/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.cs
new file mode 100644
index 00000000..41f89b66
--- /dev/null
+++ b/src/WireMock.Net.FluentAssertions/Assertions/WireMockAssertions.cs
@@ -0,0 +1,37 @@
+using System.Linq;
+using FluentAssertions;
+using FluentAssertions.Execution;
+using WireMock.Server;
+
+// ReSharper disable once CheckNamespace
+namespace WireMock.FluentAssertions
+{
+ public class WireMockAssertions
+ {
+ private readonly WireMockServer _instance;
+
+ public WireMockAssertions(WireMockServer instance, int? callsCount)
+ {
+ _instance = instance;
+ }
+
+ [CustomAssertion]
+ public AndConstraint AtAbsoluteUrl(string absoluteUrl, string because = "", params object[] becauseArgs)
+ {
+ Execute.Assertion
+ .BecauseOf(because, becauseArgs)
+ .Given(() => _instance.LogEntries.Select(x => x.RequestMessage).ToList())
+ .ForCondition(requests => requests.Any())
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the absolute url {0}{reason}, but no calls were made.",
+ absoluteUrl)
+ .Then
+ .ForCondition(x => x.Any(y => y.AbsoluteUrl == absoluteUrl))
+ .FailWith(
+ "Expected {context:wiremockserver} to have been called at address matching the absolute url {0}{reason}, but didn't find it among the calls to {1}.",
+ _ => absoluteUrl, requests => requests.Select(request => request.AbsoluteUrl));
+
+ return new AndConstraint(this);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.FluentAssertions/Assertions/WireMockReceivedAssertions.cs b/src/WireMock.Net.FluentAssertions/Assertions/WireMockReceivedAssertions.cs
new file mode 100644
index 00000000..1728a895
--- /dev/null
+++ b/src/WireMock.Net.FluentAssertions/Assertions/WireMockReceivedAssertions.cs
@@ -0,0 +1,26 @@
+using FluentAssertions.Primitives;
+using WireMock.Server;
+
+// ReSharper disable once CheckNamespace
+namespace WireMock.FluentAssertions
+{
+ public class WireMockReceivedAssertions : ReferenceTypeAssertions
+ {
+ public WireMockReceivedAssertions(WireMockServer server)
+ {
+ Subject = server;
+ }
+
+ public WireMockAssertions HaveReceivedACall()
+ {
+ return new WireMockAssertions(Subject, null);
+ }
+
+ public WireMockANumberOfCallsAssertions HaveReceived(int callsCount)
+ {
+ return new WireMockANumberOfCallsAssertions(Subject, callsCount);
+ }
+
+ protected override string Identifier => "wiremockserver";
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.FluentAssertions/Extensions/WireMockExtensions.cs b/src/WireMock.Net.FluentAssertions/Extensions/WireMockExtensions.cs
new file mode 100644
index 00000000..cd174e4e
--- /dev/null
+++ b/src/WireMock.Net.FluentAssertions/Extensions/WireMockExtensions.cs
@@ -0,0 +1,13 @@
+using WireMock.Server;
+
+// ReSharper disable once CheckNamespace
+namespace WireMock.FluentAssertions
+{
+ public static class WireMockExtensions
+ {
+ public static WireMockReceivedAssertions Should(this WireMockServer instance)
+ {
+ return new WireMockReceivedAssertions(instance);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/WireMock.Net.FluentAssertions/WireMock.Net.FluentAssertions.csproj b/src/WireMock.Net.FluentAssertions/WireMock.Net.FluentAssertions.csproj
new file mode 100644
index 00000000..74bd4ef4
--- /dev/null
+++ b/src/WireMock.Net.FluentAssertions/WireMock.Net.FluentAssertions.csproj
@@ -0,0 +1,41 @@
+
+
+
+ 1.2.13-preview-01
+ FluentAssertions extensions for WireMock.Net
+ WireMock.Net.FluentAssertions
+ Mahmoud Ali;Stef Heyenrath
+ netstandard1.3;netstandard2.0;netstandard2.1;net45
+ true
+ WireMock.Net.FluentAssertions
+ WireMock.Net.FluentAssertions
+ wiremock;FluentAssertions;UnitTest;Assert;Assertions
+ WireMock.FluentAssertions
+ {B6269AAC-170A-4346-8B9A-579DED3D9A95}
+ true
+ $(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb
+ true
+ true
+ true
+ ../WireMock.Net/WireMock.Net.ruleset
+ true
+ ../WireMock.Net/WireMock.Net.snk
+
+ true
+
+
+
+ true
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/WireMock.Net/Logging/LogEntry.cs b/src/WireMock.Net/Logging/LogEntry.cs
index a1d17d34..053a8d66 100644
--- a/src/WireMock.Net/Logging/LogEntry.cs
+++ b/src/WireMock.Net/Logging/LogEntry.cs
@@ -1,59 +1,83 @@
-using System;
-using WireMock.Matchers.Request;
-
-namespace WireMock.Logging
-{
- ///
- /// LogEntry
- ///
- public class LogEntry
- {
- ///
- /// Gets or sets the unique identifier.
- ///
- ///
- /// The unique identifier.
- ///
- public Guid Guid { get; set; }
-
- ///
- /// Gets or sets the request message.
- ///
- ///
- /// The request message.
- ///
- public RequestMessage RequestMessage { get; set; }
-
- ///
- /// Gets or sets the response message.
- ///
- ///
- /// The response message.
- ///
- public ResponseMessage ResponseMessage { get; set; }
-
- ///
- /// Gets or sets the request match result.
- ///
- ///
- /// The request match result.
- ///
- public RequestMatchResult RequestMatchResult { get; set; }
-
- ///
- /// Gets or sets the mapping unique identifier.
- ///
- ///
- /// The mapping unique identifier.
- ///
- public Guid? MappingGuid { get; set; }
-
- ///
- /// Gets or sets the mapping unique title.
- ///
- ///
- /// The mapping unique title.
- ///
- public string MappingTitle { get; set; }
- }
+using System;
+using WireMock.Matchers.Request;
+
+namespace WireMock.Logging
+{
+ ///
+ /// LogEntry
+ ///
+ public class LogEntry
+ {
+ ///
+ /// Gets or sets the unique identifier.
+ ///
+ ///
+ /// The unique identifier.
+ ///
+ public Guid Guid { get; set; }
+
+ ///
+ /// Gets or sets the request message.
+ ///
+ ///
+ /// The request message.
+ ///
+ public RequestMessage RequestMessage { get; set; }
+
+ ///
+ /// Gets or sets the response message.
+ ///
+ ///
+ /// The response message.
+ ///
+ public ResponseMessage ResponseMessage { get; set; }
+
+ ///
+ /// Gets or sets the request match result.
+ ///
+ ///
+ /// The request match result.
+ ///
+ public RequestMatchResult RequestMatchResult { get; set; }
+
+ ///
+ /// Gets or sets the mapping unique identifier.
+ ///
+ ///
+ /// The mapping unique identifier.
+ ///
+ public Guid? MappingGuid { get; set; }
+
+ ///
+ /// Gets or sets the mapping unique title.
+ ///
+ ///
+ /// The mapping unique title.
+ ///
+ public string MappingTitle { get; set; }
+
+ ///
+ /// Gets or sets the partial mapping unique identifier.
+ ///
+ ///
+ /// The mapping unique identifier.
+ ///
+ public Guid? PartialMappingGuid { get; set; }
+
+ ///
+ /// Gets or sets the partial mapping unique title.
+ ///
+ ///
+ /// The mapping unique title.
+ ///
+ public string PartialMappingTitle { get; set; }
+
+ ///
+ /// Gets or sets the partial match result.
+ ///
+ ///
+ /// The request match result.
+ ///
+ public RequestMatchResult PartialMatchResult { get; set; }
+ }
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/IMappingMatcher.cs b/src/WireMock.Net/Owin/IMappingMatcher.cs
index 54960c00..a1e54e7b 100644
--- a/src/WireMock.Net/Owin/IMappingMatcher.cs
+++ b/src/WireMock.Net/Owin/IMappingMatcher.cs
@@ -1,7 +1,7 @@
-namespace WireMock.Owin
-{
- internal interface IMappingMatcher
- {
- MappingMatcherResult FindBestMatch(RequestMessage request);
- }
+namespace WireMock.Owin
+{
+ internal interface IMappingMatcher
+ {
+ (MappingMatcherResult Match, MappingMatcherResult Partial) FindBestMatch(RequestMessage request);
+ }
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/MappingMatcher.cs b/src/WireMock.Net/Owin/MappingMatcher.cs
index e6f15398..681b1570 100644
--- a/src/WireMock.Net/Owin/MappingMatcher.cs
+++ b/src/WireMock.Net/Owin/MappingMatcher.cs
@@ -16,7 +16,7 @@ namespace WireMock.Owin
_options = options;
}
- public MappingMatcherResult FindBestMatch(RequestMessage request)
+ public (MappingMatcherResult Match, MappingMatcherResult Partial) FindBestMatch(RequestMessage request)
{
var mappings = new List();
foreach (var mapping in _options.Mappings.Values)
@@ -37,21 +37,24 @@ namespace WireMock.Owin
}
}
+ var partialMappings = mappings
+ .Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
+ .OrderBy(m => m.RequestMatchResult)
+ .ThenBy(m => m.Mapping.Priority)
+ .ToList();
+ var partialMatch = partialMappings.FirstOrDefault(pm => pm.RequestMatchResult.AverageTotalScore > 0.0);
+
if (_options.AllowPartialMapping == true)
{
- var partialMappings = mappings
- .Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
- .OrderBy(m => m.RequestMatchResult)
- .ThenBy(m => m.Mapping.Priority)
- .ToList();
-
- return partialMappings.FirstOrDefault(pm => pm.RequestMatchResult.AverageTotalScore > 0.0);
+ return (partialMatch, partialMatch);
}
- return mappings
+ var match = mappings
.Where(m => m.RequestMatchResult.IsPerfectMatch)
.OrderBy(m => m.Mapping.Priority).ThenBy(m => m.RequestMatchResult)
.FirstOrDefault();
+
+ return (match, partialMatch);
}
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/WireMockMiddleware.cs b/src/WireMock.Net/Owin/WireMockMiddleware.cs
index c225c94f..9cf01318 100644
--- a/src/WireMock.Net/Owin/WireMockMiddleware.cs
+++ b/src/WireMock.Net/Owin/WireMockMiddleware.cs
@@ -2,6 +2,7 @@ using System;
using System.Threading.Tasks;
using WireMock.Logging;
using System.Linq;
+using System.Text.RegularExpressions;
using WireMock.Matchers;
using Newtonsoft.Json;
using WireMock.Http;
@@ -73,7 +74,7 @@ namespace WireMock.Owin
bool logRequest = false;
ResponseMessage response = null;
- MappingMatcherResult result = null;
+ (MappingMatcherResult Match, MappingMatcherResult Partial) result = (null, null);
try
{
foreach (var mapping in _options.Mappings.Values.Where(m => m?.Scenario != null))
@@ -90,7 +91,7 @@ namespace WireMock.Owin
result = _mappingMatcher.FindBestMatch(request);
- var targetMapping = result?.Mapping;
+ var targetMapping = result.Match?.Mapping;
if (targetMapping == null)
{
logRequest = true;
@@ -128,7 +129,7 @@ namespace WireMock.Owin
}
catch (Exception ex)
{
- _options.Logger.Error($"Providing a Response for Mapping '{result?.Mapping?.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}");
+ _options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping?.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}");
response = ResponseMessageBuilder.Create(ex.Message, 500);
}
finally
@@ -138,9 +139,14 @@ namespace WireMock.Owin
Guid = Guid.NewGuid(),
RequestMessage = request,
ResponseMessage = response,
- MappingGuid = result?.Mapping?.Guid,
- MappingTitle = result?.Mapping?.Title,
- RequestMatchResult = result?.RequestMatchResult
+
+ MappingGuid = result.Match?.Mapping?.Guid,
+ MappingTitle = result.Match?.Mapping?.Title,
+ RequestMatchResult = result.Match?.RequestMatchResult,
+
+ PartialMappingGuid = result.Partial?.Mapping?.Guid,
+ PartialMappingTitle = result.Partial?.Mapping?.Title,
+ PartialMatchResult = result.Partial?.RequestMatchResult
};
LogRequest(log, logRequest);
diff --git a/src/WireMock.Net/Serialization/LogEntryMapper.cs b/src/WireMock.Net/Serialization/LogEntryMapper.cs
index 610c77ed..b20b1471 100644
--- a/src/WireMock.Net/Serialization/LogEntryMapper.cs
+++ b/src/WireMock.Net/Serialization/LogEntryMapper.cs
@@ -2,6 +2,7 @@
using WireMock.Admin.Mappings;
using WireMock.Admin.Requests;
using WireMock.Logging;
+using WireMock.Matchers.Request;
using WireMock.ResponseBuilders;
using WireMock.Types;
@@ -110,22 +111,37 @@ namespace WireMock.Serialization
return new LogEntryModel
{
Guid = logEntry.Guid,
- MappingGuid = logEntry.MappingGuid,
- MappingTitle = logEntry.MappingTitle,
Request = logRequestModel,
Response = logResponseModel,
- RequestMatchResult = logEntry.RequestMatchResult != null ? new LogRequestMatchModel
+
+ MappingGuid = logEntry.MappingGuid,
+ MappingTitle = logEntry.MappingTitle,
+ RequestMatchResult = Map(logEntry.RequestMatchResult),
+
+ PartialMappingGuid = logEntry.PartialMappingGuid,
+ PartialMappingTitle = logEntry.PartialMappingTitle,
+ PartialRequestMatchResult = Map(logEntry.PartialMatchResult)
+ };
+ }
+
+ private static LogRequestMatchModel Map(RequestMatchResult matchResult)
+ {
+ if (matchResult == null)
+ {
+ return null;
+ }
+
+ return new LogRequestMatchModel
+ {
+ IsPerfectMatch = matchResult.IsPerfectMatch,
+ TotalScore = matchResult.TotalScore,
+ TotalNumber = matchResult.TotalNumber,
+ AverageTotalScore = matchResult.AverageTotalScore,
+ MatchDetails = matchResult.MatchDetails.Select(md => new
{
- IsPerfectMatch = logEntry.RequestMatchResult.IsPerfectMatch,
- TotalScore = logEntry.RequestMatchResult.TotalScore,
- TotalNumber = logEntry.RequestMatchResult.TotalNumber,
- AverageTotalScore = logEntry.RequestMatchResult.AverageTotalScore,
- MatchDetails = logEntry.RequestMatchResult.MatchDetails.Select(md => new
- {
- Name = md.MatcherType.Name.Replace("RequestMessage", string.Empty),
- Score = md.Score
- } as object).ToList()
- } : null
+ Name = md.MatcherType.Name.Replace("RequestMessage", string.Empty),
+ Score = md.Score
+ } as object).ToList()
};
}
}
diff --git a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
index a30ba998..5c9377d7 100644
--- a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
+++ b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
@@ -1,153 +1,191 @@
-using System;
-using System.Collections.Concurrent;
-using Moq;
-using NFluent;
-using WireMock.Logging;
-using WireMock.Matchers.Request;
-using WireMock.Models;
-using WireMock.Owin;
-using WireMock.Util;
-using Xunit;
-
-namespace WireMock.Net.Tests.Owin
-{
- public class MappingMatcherTests
- {
- private readonly Mock _optionsMock;
- private readonly MappingMatcher _sut;
-
- public MappingMatcherTests()
- {
- _optionsMock = new Mock();
- _optionsMock.SetupAllProperties();
- _optionsMock.Setup(o => o.Mappings).Returns(new ConcurrentDictionary());
- _optionsMock.Setup(o => o.LogEntries).Returns(new ConcurrentObservableCollection());
- _optionsMock.Setup(o => o.Scenarios).Returns(new ConcurrentDictionary());
-
- var loggerMock = new Mock();
- loggerMock.SetupAllProperties();
- loggerMock.Setup(l => l.Error(It.IsAny()));
- _optionsMock.Setup(o => o.Logger).Returns(loggerMock.Object);
-
- _sut = new MappingMatcher(_optionsMock.Object);
- }
-
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenNoMappingsDefined_ShouldReturnNull()
- {
- // Assign
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
-
- // Act
- var result = _sut.FindBestMatch(request);
-
- // Assert and Verify
- Check.That(result).IsNull();
- }
-
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenMappingThrowsException_ShouldReturnNull()
- {
- // Assign
- var mappingMock = new Mock();
- mappingMock.Setup(m => m.GetRequestMatchResult(It.IsAny(), It.IsAny())).Throws();
-
- var mappings = new ConcurrentDictionary();
- mappings.TryAdd(Guid.NewGuid(), mappingMock.Object);
-
- _optionsMock.Setup(o => o.Mappings).Returns(mappings);
-
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
-
- // Act
- var result = _sut.FindBestMatch(request);
-
- // Assert and Verify
- Check.That(result).IsNull();
- }
-
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_ShouldReturnExactMatch()
- {
- // Assign
- var mappings = InitMappings(
- (Guid.Parse("00000000-0000-0000-0000-000000000001"), new[] { 0.1 }),
- (Guid.Parse("00000000-0000-0000-0000-000000000002"), new[] { 1.0 })
- );
- _optionsMock.Setup(o => o.Mappings).Returns(mappings);
-
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
-
- // Act
- var result = _sut.FindBestMatch(request);
-
- // Assert and Verify
- Check.That(result.Mapping.Guid).IsEqualTo(Guid.Parse("00000000-0000-0000-0000-000000000002"));
- Check.That(result.RequestMatchResult.AverageTotalScore).IsEqualTo(1.0);
- }
-
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsTrue_ShouldReturnAnyMatch()
- {
- // Assign
- _optionsMock.SetupGet(o => o.AllowPartialMapping).Returns(true);
- var mappings = InitMappings(
- (Guid.Parse("00000000-0000-0000-0000-000000000001"), new[] { 0.1 }),
- (Guid.Parse("00000000-0000-0000-0000-000000000002"), new[] { 0.9 })
- );
- _optionsMock.Setup(o => o.Mappings).Returns(mappings);
-
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
-
- // Act
- var result = _sut.FindBestMatch(request);
-
- // Assert and Verify
- Check.That(result.Mapping.Guid).IsEqualTo(Guid.Parse("00000000-0000-0000-0000-000000000002"));
- Check.That(result.RequestMatchResult.AverageTotalScore).IsEqualTo(0.9);
- }
-
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_And_WithSameAverageScoreButMoreMatchers_ReturnsMatchWithMoreMatchers()
- {
- // Assign
- var mappings = InitMappings(
- (Guid.Parse("00000000-0000-0000-0000-000000000001"), new[] { 1.0 }),
- (Guid.Parse("00000000-0000-0000-0000-000000000002"), new[] { 1.0, 1.0 })
- );
- _optionsMock.Setup(o => o.Mappings).Returns(mappings);
-
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
-
- // Act
- var result = _sut.FindBestMatch(request);
-
- // Assert and Verify
- Check.That(result.Mapping.Guid).IsEqualTo(Guid.Parse("00000000-0000-0000-0000-000000000002"));
- Check.That(result.RequestMatchResult.AverageTotalScore).IsEqualTo(1.0);
- }
-
- private ConcurrentDictionary InitMappings(params (Guid guid, double[] scores)[] matches)
- {
- var mappings = new ConcurrentDictionary();
-
- foreach (var match in matches)
- {
- var mappingMock = new Mock();
- mappingMock.SetupGet(m => m.Guid).Returns(match.guid);
-
- var requestMatchResult = new RequestMatchResult();
- foreach (var score in match.scores)
- {
- requestMatchResult.AddScore(typeof(object), score);
- }
-
- mappingMock.Setup(m => m.GetRequestMatchResult(It.IsAny(), It.IsAny())).Returns(requestMatchResult);
-
- mappings.TryAdd(match.guid, mappingMock.Object);
- }
-
- return mappings;
- }
- }
+using System;
+using System.Collections.Concurrent;
+using FluentAssertions;
+using Moq;
+using WireMock.Logging;
+using WireMock.Matchers.Request;
+using WireMock.Models;
+using WireMock.Owin;
+using WireMock.Util;
+using Xunit;
+
+namespace WireMock.Net.Tests.Owin
+{
+ public class MappingMatcherTests
+ {
+ private readonly Mock _optionsMock;
+ private readonly MappingMatcher _sut;
+
+ public MappingMatcherTests()
+ {
+ _optionsMock = new Mock();
+ _optionsMock.SetupAllProperties();
+ _optionsMock.Setup(o => o.Mappings).Returns(new ConcurrentDictionary());
+ _optionsMock.Setup(o => o.LogEntries).Returns(new ConcurrentObservableCollection());
+ _optionsMock.Setup(o => o.Scenarios).Returns(new ConcurrentDictionary());
+
+ var loggerMock = new Mock();
+ loggerMock.SetupAllProperties();
+ loggerMock.Setup(l => l.Error(It.IsAny()));
+ _optionsMock.Setup(o => o.Logger).Returns(loggerMock.Object);
+
+ _sut = new MappingMatcher(_optionsMock.Object);
+ }
+
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenNoMappingsDefined_ShouldReturnNull()
+ {
+ // Assign
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert
+ result.Match.Should().BeNull();
+ result.Partial.Should().BeNull();
+ }
+
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenMappingThrowsException_ShouldReturnNull()
+ {
+ // Assign
+ var mappingMock = new Mock();
+ mappingMock.Setup(m => m.GetRequestMatchResult(It.IsAny(), It.IsAny())).Throws();
+
+ var mappings = new ConcurrentDictionary();
+ mappings.TryAdd(Guid.NewGuid(), mappingMock.Object);
+
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert
+ result.Match.Should().BeNull();
+ result.Partial.Should().BeNull();
+ }
+
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_ShouldReturnExactMatch()
+ {
+ // Assign
+ var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
+ var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
+ var mappings = InitMappings(
+ (guid1, new[] { 0.1 }),
+ (guid2, new[] { 1.0 })
+ );
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert
+ result.Match.Mapping.Guid.Should().Be(guid2);
+ result.Match.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
+ result.Partial.Mapping.Guid.Should().Be(guid2);
+ result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
+ }
+
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_AndNoExactmatch_ShouldReturnNullExactMatch_And_PartialMatch()
+ {
+ // Assign
+ var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
+ var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
+ var mappings = InitMappings(
+ (guid1, new[] { 0.1 }),
+ (guid2, new[] { 0.9 })
+ );
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert
+ result.Match.Should().BeNull();
+ result.Partial.Mapping.Guid.Should().Be(guid2);
+ result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(0.9);
+ }
+
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsTrue_ShouldReturnAnyMatch()
+ {
+ // Assign
+ var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
+ var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
+
+ _optionsMock.SetupGet(o => o.AllowPartialMapping).Returns(true);
+ var mappings = InitMappings(
+ (guid1, new[] { 0.1 }),
+ (guid2, new[] { 0.9 })
+ );
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert
+ result.Match.Mapping.Guid.Should().Be(guid2);
+ result.Match.RequestMatchResult.AverageTotalScore.Should().Be(0.9);
+ result.Partial.Mapping.Guid.Should().Be(guid2);
+ result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(0.9);
+ }
+
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_And_WithSameAverageScoreButMoreMatchers_ReturnsMatchWithMoreMatchers()
+ {
+ // Assign
+ var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
+ var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
+ var mappings = InitMappings(
+ (guid1, new[] { 1.0 }),
+ (guid2, new[] { 1.0, 1.0 })
+ );
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert and Verify
+ result.Match.Mapping.Guid.Should().Be(guid2);
+ result.Match.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
+ result.Partial.Mapping.Guid.Should().Be(guid2);
+ result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
+ }
+
+ private ConcurrentDictionary InitMappings(params (Guid guid, double[] scores)[] matches)
+ {
+ var mappings = new ConcurrentDictionary();
+
+ foreach (var match in matches)
+ {
+ var mappingMock = new Mock();
+ mappingMock.SetupGet(m => m.Guid).Returns(match.guid);
+
+ var requestMatchResult = new RequestMatchResult();
+ foreach (var score in match.scores)
+ {
+ requestMatchResult.AddScore(typeof(object), score);
+ }
+
+ mappingMock.Setup(m => m.GetRequestMatchResult(It.IsAny(), It.IsAny())).Returns(requestMatchResult);
+
+ mappings.TryAdd(match.guid, mappingMock.Object);
+ }
+
+ return mappings;
+ }
+ }
}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
index 9c1eb326..0fcc0130 100644
--- a/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
+++ b/test/WireMock.Net.Tests/Owin/WireMockMiddlewareTests.cs
@@ -60,7 +60,7 @@ namespace WireMock.Net.Tests.Owin
_matcherMock = new Mock();
_matcherMock.SetupAllProperties();
- _matcherMock.Setup(m => m.FindBestMatch(It.IsAny())).Returns(new MappingMatcherResult());
+ _matcherMock.Setup(m => m.FindBestMatch(It.IsAny())).Returns((new MappingMatcherResult(), new MappingMatcherResult()));
_contextMock = new Mock();
@@ -78,7 +78,7 @@ namespace WireMock.Net.Tests.Owin
// Assert and Verify
_optionsMock.Verify(o => o.Logger.Warn(It.IsAny(), It.IsAny