This commit is contained in:
Stef Heyenrath
2026-01-11 18:05:35 +01:00
parent 041d16e658
commit 83922fd543
11 changed files with 63 additions and 18 deletions

View File

@@ -1,6 +1,7 @@
// Copyright © WireMock.Net // Copyright © WireMock.Net
using System.Collections.Generic; using System.Collections.Generic;
using WireMock.Matchers.Request;
namespace WireMock.Admin.Requests; namespace WireMock.Admin.Requests;
@@ -47,5 +48,5 @@ public class LogRequestMatchModel
/// <value> /// <value>
/// The match details. /// The match details.
/// </value> /// </value>
public IList<object> MatchDetails { get; set; } = []; public IList<MatchDetail> MatchDetails { get; set; } = [];
} }

View File

@@ -55,4 +55,11 @@ public interface IRequestMatchResult : IComparable
/// <param name="exception">The exception [Optional].</param> /// <param name="exception">The exception [Optional].</param>
/// <returns>The score.</returns> /// <returns>The score.</returns>
double AddScore(Type matcherType, double score, Exception? exception); double AddScore(Type matcherType, double score, Exception? exception);
/// <summary>
/// Adds the score.
/// </summary>
/// <param name="matchDetail">The matchDetail.</param>
/// <returns>The score.</returns>
double AddMatchDetail(MatchDetail matchDetail);
} }

View File

@@ -14,6 +14,11 @@ public class MatchDetail
/// </summary> /// </summary>
public required Type MatcherType { get; set; } public required Type MatcherType { get; set; }
/// <summary>
/// Gets or sets the type of the matcher.
/// </summary>
public required string Name { get; set; }
/// <summary> /// <summary>
/// Gets or sets the score between 0.0 and 1.0 /// Gets or sets the score between 0.0 and 1.0
/// </summary> /// </summary>
@@ -24,4 +29,9 @@ public class MatchDetail
/// [Optional] /// [Optional]
/// </summary> /// </summary>
public Exception? Exception { get; set; } public Exception? Exception { get; set; }
/// <summary>
/// The child MatchResults in case of multiple matchers.
/// </summary>
public MatchDetail[]? MatchDetails { get; set; }
} }

View File

@@ -69,7 +69,7 @@ public class WireMockConsoleLogger : IWireMockLogger
/// <see cref="IWireMockLogger.DebugRequestResponse"/> /// <see cref="IWireMockLogger.DebugRequestResponse"/>
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest) public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
{ {
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented); string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented, new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore });
Console.WriteLine(Format("DebugRequestResponse", "Admin[{0}] {1}", isAdminRequest, message)); Console.WriteLine(Format("DebugRequestResponse", "Admin[{0}] {1}", isAdminRequest, message));
} }

View File

@@ -31,6 +31,7 @@ public class RequestMatchResult : IRequestMatchResult
{ {
MatchDetails.Add(new MatchDetail MatchDetails.Add(new MatchDetail
{ {
Name = matcherType.Name.Replace("RequestMessage", string.Empty),
MatcherType = matcherType, MatcherType = matcherType,
Score = score, Score = score,
Exception = exception Exception = exception
@@ -39,6 +40,14 @@ public class RequestMatchResult : IRequestMatchResult
return score; return score;
} }
/// <inheritdoc />
public double AddMatchDetail(MatchDetail matchDetail)
{
MatchDetails.Add(matchDetail);
return matchDetail.Score;
}
/// <summary> /// <summary>
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object. /// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
/// </summary> /// </summary>

View File

@@ -79,8 +79,8 @@ public class RequestMessageClientIPMatcher : IRequestMatcher
/// <inheritdoc /> /// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{ {
var (score, exception) = GetMatchResult(requestMessage).Expand(); var matchDetail = GetMatchResult(requestMessage).ToMatchDetail();
return requestMatchResult.AddScore(GetType(), score, exception); return requestMatchResult.AddMatchDetail(matchDetail);
} }
private MatchResult GetMatchResult(IRequestMessage requestMessage) private MatchResult GetMatchResult(IRequestMessage requestMessage)

View File

@@ -15,7 +15,7 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher
/// <summary> /// <summary>
/// The name of this matcher. /// The name of this matcher.
/// </summary> /// </summary>
public const string MatcherName = "MultiPartMatcher"; public const string Name = "MultiPartMatcher";
private readonly IMimeKitUtils _mimeKitUtils = LoadMimeKitUtils(); private readonly IMimeKitUtils _mimeKitUtils = LoadMimeKitUtils();
@@ -59,19 +59,20 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher
/// <inheritdoc /> /// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{ {
var score = MatchScores.Mismatch; var matchDetail = MatchResult.From(Name).ToMatchDetail();
Exception? exception = null; Exception? exception = null;
if (Matchers == null) if (Matchers == null)
{ {
return requestMatchResult.AddScore(GetType(), score, null); return requestMatchResult.AddMatchDetail(matchDetail);
} }
if (!_mimeKitUtils.TryGetMimeMessage(requestMessage, out var message)) if (!_mimeKitUtils.TryGetMimeMessage(requestMessage, out var message))
{ {
return requestMatchResult.AddScore(GetType(), score, null); return requestMatchResult.AddMatchDetail(matchDetail);
} }
double score = MatchScores.Mismatch;
try try
{ {
foreach (var mimePartMatcher in Matchers.OfType<IMimePartMatcher>().ToArray()) foreach (var mimePartMatcher in Matchers.OfType<IMimePartMatcher>().ToArray())
@@ -99,7 +100,7 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher
exception = ex; exception = ex;
} }
return requestMatchResult.AddScore(GetType(), score, exception); return requestMatchResult.AddMatchDetail(MatchResult.From(Name, score, exception).ToMatchDetail());
} }
private static IMimeKitUtils LoadMimeKitUtils() private static IMimeKitUtils LoadMimeKitUtils()

View File

@@ -77,8 +77,8 @@ public class RequestMessagePathMatcher : IRequestMatcher
/// <inheritdoc /> /// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult) public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{ {
var (score, exception) = GetMatchResult(requestMessage).Expand(); var matchDetail = GetMatchResult(requestMessage).ToMatchDetail();
return requestMatchResult.AddScore(GetType(), score, exception); return requestMatchResult.AddMatchDetail(matchDetail);
} }
private MatchResult GetMatchResult(IRequestMessage requestMessage) private MatchResult GetMatchResult(IRequestMessage requestMessage)

View File

@@ -166,11 +166,12 @@ internal class LogEntryMapper
TotalScore = matchResult.TotalScore, TotalScore = matchResult.TotalScore,
TotalNumber = matchResult.TotalNumber, TotalNumber = matchResult.TotalNumber,
AverageTotalScore = matchResult.AverageTotalScore, AverageTotalScore = matchResult.AverageTotalScore,
MatchDetails = matchResult.MatchDetails.Select(md => new MatchDetails = matchResult.MatchDetails
{ //MatchDetails = matchResult.MatchDetails.Select(md => new
Name = md.MatcherType.Name.Replace("RequestMessage", string.Empty), //{
md.Score // Name = md.MatcherType.Name.Replace("RequestMessage", string.Empty),
} as object).ToList() // md.Score
//} as object).ToList()
}; };
} }
} }

View File

@@ -255,7 +255,7 @@ public partial class WireMockServer
{ {
var matchOperator = StringUtils.ParseMatchOperator(requestModel.Body.MatchOperator); var matchOperator = StringUtils.ParseMatchOperator(requestModel.Body.MatchOperator);
if (requestModel.Body.MatcherName == RequestMessageMultiPartMatcher.MatcherName) if (requestModel.Body.MatcherName == RequestMessageMultiPartMatcher.Name)
{ {
requestBuilder = requestBuilder.WithMultiPart(_matcherMapper.Map(requestModel.Body.Matchers), matchOperator: matchOperator); requestBuilder = requestBuilder.WithMultiPart(_matcherMapper.Map(requestModel.Body.Matchers), matchOperator: matchOperator);
} }

View File

@@ -5,6 +5,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using Stef.Validation; using Stef.Validation;
using WireMock.Extensions; using WireMock.Extensions;
using WireMock.Matchers.Request;
namespace WireMock.Matchers; namespace WireMock.Matchers;
@@ -30,7 +31,7 @@ public class MatchResult
public required string Name { get; set; } public required string Name { get; set; }
/// <summary> /// <summary>
/// The sub MatchResults in case of multiple matchers. /// The child MatchResults in case of multiple matchers.
/// </summary> /// </summary>
public MatchResult[]? MatchResults { get; set; } public MatchResult[]? MatchResults { get; set; }
@@ -99,4 +100,19 @@ public class MatchResult
{ {
return (Score, Exception); return (Score, Exception);
} }
/// <summary>
/// Convert to <see cref="MatchResult"/>.
/// </summary>
public MatchDetail ToMatchDetail()
{
return new MatchDetail
{
Name = Name,
MatcherType = typeof(MatchResult),
Score = Score,
Exception = Exception,
MatchDetails = MatchResults?.Select(mr => mr.ToMatchDetail()).ToArray()
};
}
} }