mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-24 09:48:51 +02:00
Merge branch 'master' into version-2.x
This commit is contained in:
@@ -1,3 +1,12 @@
|
|||||||
|
# 1.17.0 (07 December 2025)
|
||||||
|
- [#1383](https://github.com/wiremock/WireMock.Net/pull/1383) - Aspire: Add WithProtoDefinition to support proto definition at server level [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#1386](https://github.com/wiremock/WireMock.Net/pull/1386) - Fix random delay in mapping json file [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#1274](https://github.com/wiremock/WireMock.Net/issues/1274) - .WithMappings to mount volume is not working for GRPC [bug]
|
||||||
|
- [#1381](https://github.com/wiremock/WireMock.Net/issues/1381) - Downstream dependencies missing after 1.16.0 release [bug]
|
||||||
|
- [#1382](https://github.com/wiremock/WireMock.Net/issues/1382) - Does Aspire support enabling HTTP/2? [feature]
|
||||||
|
- [#1385](https://github.com/wiremock/WireMock.Net/issues/1385) - Do delays and probabilities show in saved static mappings? [bug]
|
||||||
|
- [#1387](https://github.com/wiremock/WireMock.Net/issues/1387) - Tests failing with TaskCanceledException on Windows Server 2025 Build 7171 [bug]
|
||||||
|
|
||||||
# 1.16.0 (18 November 2025)
|
# 1.16.0 (18 November 2025)
|
||||||
- [#1366](https://github.com/wiremock/WireMock.Net/pull/1366) - WireMock.Net.OpenApiParser : support Examples [feature] contributed by [StefH](https://github.com/StefH)
|
- [#1366](https://github.com/wiremock/WireMock.Net/pull/1366) - WireMock.Net.OpenApiParser : support Examples [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#1375](https://github.com/wiremock/WireMock.Net/pull/1375) - Add WireMockHealthCheck in WireMock.Net.Aspire [feature] contributed by [Zguy](https://github.com/Zguy)
|
- [#1375](https://github.com/wiremock/WireMock.Net/pull/1375) - Add WireMockHealthCheck in WireMock.Net.Aspire [feature] contributed by [Zguy](https://github.com/Zguy)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>1.16.0</VersionPrefix>
|
<VersionPrefix>1.17.0</VersionPrefix>
|
||||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||||
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
||||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
rem https://github.com/StefH/GitHubReleaseNotes
|
rem https://github.com/StefH/GitHubReleaseNotes
|
||||||
|
|
||||||
SET version=1.16.0
|
SET version=1.17.0
|
||||||
|
|
||||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels wontfix test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
|
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels wontfix test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
# 1.16.0 (18 November 2025)
|
# 1.17.0 (07 December 2025)
|
||||||
- #1366 WireMock.Net.OpenApiParser : support Examples [feature]
|
- #1383 Aspire: Add WithProtoDefinition to support proto definition at server level [feature]
|
||||||
- #1375 Add WireMockHealthCheck in WireMock.Net.Aspire [feature]
|
- #1386 Fix random delay in mapping json file [bug]
|
||||||
- #1377 Check if the path is valid when using WithPath(...) [feature]
|
- #812 Wiki page for using WireMock.Net with appium for mobile automation testing [wontfix]
|
||||||
- #1380 Add WireMock.Net.xUnit.v3 project [feature]
|
- #1274 .WithMappings to mount volume is not working for GRPC [bug]
|
||||||
- #1364 Choosing examples from open api specification for responses. [feature]
|
- #1381 Downstream dependencies missing after 1.16.0 release [bug]
|
||||||
- #1376 AdminApiMappingBuilder `WithPath` should add the starting `/` if missing [feature]
|
- #1382 Does Aspire support enabling HTTP/2? [feature]
|
||||||
- #1379 xUnit v3 [feature]
|
- #1385 Do delays and probabilities show in saved static mappings? [bug]
|
||||||
|
- #1387 Tests failing with TaskCanceledException on Windows Server 2025 Build 7171 [bug]
|
||||||
|
|
||||||
The full release notes can be found here: https://github.com/wiremock/WireMock.Net/blob/master/CHANGELOG.md
|
The full release notes can be found here: https://github.com/wiremock/WireMock.Net/blob/master/CHANGELOG.md
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using Stef.Validation;
|
||||||
|
|
||||||
|
namespace WireMock.Matchers.Request;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The request body matcher.
|
||||||
|
/// </summary>
|
||||||
|
public class RequestMessageBodyMatcher<T> : IRequestMatcher
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The body data function for type T
|
||||||
|
/// </summary>
|
||||||
|
public Func<T?, bool>? Func { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The <see cref="MatchOperator"/>
|
||||||
|
/// </summary>
|
||||||
|
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="func">The function.</param>
|
||||||
|
public RequestMessageBodyMatcher(Func<T?, bool> func)
|
||||||
|
{
|
||||||
|
Func = Guard.NotNull(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||||
|
{
|
||||||
|
var (score, exception) = CalculateMatchScore(requestMessage).Expand();
|
||||||
|
return requestMatchResult.AddScore(GetType(), score, exception);
|
||||||
|
}
|
||||||
|
|
||||||
|
private MatchResult CalculateMatchScore(IRequestMessage requestMessage)
|
||||||
|
{
|
||||||
|
if (Func != null)
|
||||||
|
{
|
||||||
|
if (requestMessage.BodyData?.BodyAsJson is JObject jsonObject)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var bodyAsT = jsonObject.ToObject<T>();
|
||||||
|
return MatchScores.ToScore(Func(bodyAsT));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return new MatchResult(ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return default;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -34,13 +34,6 @@ public partial class Request
|
|||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
|
||||||
{
|
|
||||||
var matcher = body as IMatcher ?? new JsonMatcher(matchBehaviour, body);
|
|
||||||
return WithBody([matcher]);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder WithBody(IMatcher matcher)
|
public IRequestBuilder WithBody(IMatcher matcher)
|
||||||
{
|
{
|
||||||
@@ -98,4 +91,20 @@ public partial class Request
|
|||||||
_requestMatchers.Add(new RequestMessageBodyMatcher(Guard.NotNull(func)));
|
_requestMatchers.Add(new RequestMessageBodyMatcher(Guard.NotNull(func)));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IRequestBuilder WithBodyAsJson(object body, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
|
{
|
||||||
|
var matcher = body as IMatcher ?? new JsonMatcher(matchBehaviour, body);
|
||||||
|
return WithBody([matcher]);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IRequestBuilder WithBodyAsType<T>(Func<T?, bool> func)
|
||||||
|
{
|
||||||
|
Guard.NotNull(func);
|
||||||
|
|
||||||
|
_requestMatchers.Add(new RequestMessageBodyMatcher<T>(func));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -29,7 +29,7 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
|
|||||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||||
public static IRequestBuilder Create()
|
public static IRequestBuilder Create()
|
||||||
{
|
{
|
||||||
return new Request(new List<IRequestMatcher>());
|
return new Request([]);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -80,6 +80,14 @@ public interface IBodyRequestBuilder : IMultiPartRequestBuilder
|
|||||||
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||||
IRequestBuilder WithBody(Func<object?, bool> func);
|
IRequestBuilder WithBody(Func<object?, bool> func);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WithBody: func (type)
|
||||||
|
/// </summary>
|
||||||
|
/// <typeparam name="T">The type.</typeparam>
|
||||||
|
/// <param name="func">The function.</param>
|
||||||
|
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
|
||||||
|
IRequestBuilder WithBodyAsType<T>(Func<T?, bool> func);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// WithBody: func (BodyData object)
|
/// WithBody: func (BodyData object)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using FluentAssertions;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
|
using FluentAssertions;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
using NFluent;
|
using NFluent;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
@@ -72,15 +73,17 @@ public class RequestBuilderWithBodyTests
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Request_WithBody_FuncJson()
|
public void Request_WithBody_FuncObject()
|
||||||
{
|
{
|
||||||
// Assign
|
// Assign
|
||||||
var requestBuilder = Request.Create().UsingAnyMethod().WithBody(b => b != null);
|
var requestBuilder = Request.Create()
|
||||||
|
.UsingAnyMethod()
|
||||||
|
.WithBody(b => b != null);
|
||||||
|
|
||||||
// Act
|
// Act
|
||||||
var body = new BodyData
|
var body = new BodyData
|
||||||
{
|
{
|
||||||
BodyAsJson = 123,
|
BodyAsJson = JObject.Parse("""{ "X": 123, "Y": "a" }"""),
|
||||||
DetectedBodyType = BodyType.Json
|
DetectedBodyType = BodyType.Json
|
||||||
};
|
};
|
||||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||||
@@ -90,6 +93,57 @@ public class RequestBuilderWithBodyTests
|
|||||||
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Theory]
|
||||||
|
[InlineData("""{ "X": 123, "Y": "a" }""", 1.0)]
|
||||||
|
[InlineData("""{ "X": 123, "Y": "b" }""", 0.0)]
|
||||||
|
public void Request_WithBodyAsType_Func(string json, double expected)
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var requestBuilder = Request.Create()
|
||||||
|
.UsingAnyMethod()
|
||||||
|
.WithBodyAsType<FuncType>(ft => ft != null && ft.X == 123 && ft.Y == "a");
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var body = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsJson = JObject.Parse(json),
|
||||||
|
DetectedBodyType = BodyType.Json
|
||||||
|
};
|
||||||
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var requestMatchResult = new RequestMatchResult();
|
||||||
|
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(expected);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void Request_WithBodyAsType_Func_IncorrectType()
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var requestBuilder = Request.Create()
|
||||||
|
.UsingAnyMethod()
|
||||||
|
.WithBodyAsType<Version>(ft => ft != null);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
var body = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsJson = JObject.Parse("""{ "X": 123, "Y": "a" }"""),
|
||||||
|
DetectedBodyType = BodyType.Json
|
||||||
|
};
|
||||||
|
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, body);
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
var requestMatchResult = new RequestMatchResult();
|
||||||
|
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(0.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FuncType
|
||||||
|
{
|
||||||
|
public int X { get; set; } = 42;
|
||||||
|
|
||||||
|
public string Y { get; set; } = string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void Request_WithBody_FuncFormUrlEncoded()
|
public void Request_WithBody_FuncFormUrlEncoded()
|
||||||
{
|
{
|
||||||
|
|||||||
Reference in New Issue
Block a user