Add PartialMatch to logging / logentries (#482)

* .

* FluentAssertions

* .

* .
This commit is contained in:
Stef Heyenrath
2020-07-04 11:39:50 +02:00
committed by GitHub
parent d8c708e97c
commit c484b48c35
14 changed files with 502 additions and 250 deletions

View File

@@ -1,59 +1,83 @@
using System;
using WireMock.Matchers.Request;
namespace WireMock.Logging
{
/// <summary>
/// LogEntry
/// </summary>
public class LogEntry
{
/// <summary>
/// Gets or sets the unique identifier.
/// </summary>
/// <value>
/// The unique identifier.
/// </value>
public Guid Guid { get; set; }
/// <summary>
/// Gets or sets the request message.
/// </summary>
/// <value>
/// The request message.
/// </value>
public RequestMessage RequestMessage { get; set; }
/// <summary>
/// Gets or sets the response message.
/// </summary>
/// <value>
/// The response message.
/// </value>
public ResponseMessage ResponseMessage { get; set; }
/// <summary>
/// Gets or sets the request match result.
/// </summary>
/// <value>
/// The request match result.
/// </value>
public RequestMatchResult RequestMatchResult { get; set; }
/// <summary>
/// Gets or sets the mapping unique identifier.
/// </summary>
/// <value>
/// The mapping unique identifier.
/// </value>
public Guid? MappingGuid { get; set; }
/// <summary>
/// Gets or sets the mapping unique title.
/// </summary>
/// <value>
/// The mapping unique title.
/// </value>
public string MappingTitle { get; set; }
}
using System;
using WireMock.Matchers.Request;
namespace WireMock.Logging
{
/// <summary>
/// LogEntry
/// </summary>
public class LogEntry
{
/// <summary>
/// Gets or sets the unique identifier.
/// </summary>
/// <value>
/// The unique identifier.
/// </value>
public Guid Guid { get; set; }
/// <summary>
/// Gets or sets the request message.
/// </summary>
/// <value>
/// The request message.
/// </value>
public RequestMessage RequestMessage { get; set; }
/// <summary>
/// Gets or sets the response message.
/// </summary>
/// <value>
/// The response message.
/// </value>
public ResponseMessage ResponseMessage { get; set; }
/// <summary>
/// Gets or sets the request match result.
/// </summary>
/// <value>
/// The request match result.
/// </value>
public RequestMatchResult RequestMatchResult { get; set; }
/// <summary>
/// Gets or sets the mapping unique identifier.
/// </summary>
/// <value>
/// The mapping unique identifier.
/// </value>
public Guid? MappingGuid { get; set; }
/// <summary>
/// Gets or sets the mapping unique title.
/// </summary>
/// <value>
/// The mapping unique title.
/// </value>
public string MappingTitle { get; set; }
/// <summary>
/// Gets or sets the partial mapping unique identifier.
/// </summary>
/// <value>
/// The mapping unique identifier.
/// </value>
public Guid? PartialMappingGuid { get; set; }
/// <summary>
/// Gets or sets the partial mapping unique title.
/// </summary>
/// <value>
/// The mapping unique title.
/// </value>
public string PartialMappingTitle { get; set; }
/// <summary>
/// Gets or sets the partial match result.
/// </summary>
/// <value>
/// The request match result.
/// </value>
public RequestMatchResult PartialMatchResult { get; set; }
}
}

View File

@@ -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);
}
}

View File

@@ -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<MappingMatcherResult>();
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);
}
}
}

View File

@@ -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);

View File

@@ -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()
};
}
}