Fix FormUrlEncodedMatcher (+ refactor values / matchers logic) (#1503)

* Fix FormUrlEncodedMatcher

* tests

* Apply suggestions from code review

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>

* fix comments

---------

Co-authored-by: Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com>
Co-authored-by: Copilot Autofix powered by AI <175728472+Copilot@users.noreply.github.com>
This commit is contained in:
Stef Heyenrath
2026-08-20 17:31:16 +02:00
committed by GitHub
co-authored by Copilot Autofix powered by AI <223894421+github-code-quality[bot]@users.noreply.github.com> Copilot Autofix powered by AI
parent 2b165eb6a1
commit ee0f890795
17 changed files with 598 additions and 142 deletions
@@ -408,4 +408,210 @@ public class WireMockListTests
}
#endregion
#region Equality Operator Tests
[Fact]
public void WireMockListOfString_EqualityOperator_ListToSingleValue_WhenSingleElementMatchesValue_ShouldBeTrue()
{
// Arrange
var list = new WireMockList<string>("hello");
// Act & Assert
(list == "hello").Should().BeTrue();
}
[Fact]
public void WireMockListOfString_EqualityOperator_ListToSingleValue_WhenSingleElementDoesNotMatchValue_ShouldBeFalse()
{
// Arrange
var list = new WireMockList<string>("hello");
// Act & Assert
(list == "world").Should().BeFalse();
}
[Fact]
public void WireMockListOfString_EqualityOperator_ListToSingleValue_WhenMultipleElements_ShouldBeFalse()
{
// Arrange
var list = new WireMockList<string>("hello", "world");
// Act & Assert
(list == "hello").Should().BeFalse();
}
[Fact]
public void WireMockListOfString_EqualityOperator_SingleValueToList_WhenSingleElementMatchesValue_ShouldBeTrue()
{
// Arrange
var list = new WireMockList<string>("hello");
// Act & Assert
("hello" == list).Should().BeTrue();
}
[Fact]
public void WireMockListOfString_EqualityOperator_SingleValueToList_WhenSingleElementDoesNotMatchValue_ShouldBeFalse()
{
// Arrange
var list = new WireMockList<string>("hello");
// Act & Assert
("world" == list).Should().BeFalse();
}
[Fact]
public void WireMockListOfString_InequalityOperator_ListToSingleValue_WhenSingleElementMatchesValue_ShouldBeFalse()
{
// Arrange
var list = new WireMockList<string>("hello");
// Act & Assert
(list != "hello").Should().BeFalse();
}
[Fact]
public void WireMockListOfString_InequalityOperator_ListToSingleValue_WhenSingleElementDoesNotMatchValue_ShouldBeTrue()
{
// Arrange
var list = new WireMockList<string>("hello");
// Act & Assert
(list != "world").Should().BeTrue();
}
[Fact]
public void WireMockListOfString_InequalityOperator_SingleValueToList_WhenSingleElementMatchesValue_ShouldBeFalse()
{
// Arrange
var list = new WireMockList<string>("hello");
// Act & Assert
("hello" != list).Should().BeFalse();
}
[Fact]
public void WireMockListOfString_InequalityOperator_SingleValueToList_WhenSingleElementDoesNotMatchValue_ShouldBeTrue()
{
// Arrange
var list = new WireMockList<string>("hello");
// Act & Assert
("world" != list).Should().BeTrue();
}
#endregion
#region Equals and GetHashCode Tests
[Fact]
public void WireMockListOfString_Equals_WhenBothListsHaveSameElements_ShouldBeTrue()
{
// Arrange
var list1 = new WireMockList<string>("a", "b", "c");
var list2 = new WireMockList<string>("a", "b", "c");
// Act & Assert
list1.Equals(list2).Should().BeTrue();
}
[Fact]
public void WireMockListOfString_Equals_WhenListsHaveDifferentElements_ShouldBeFalse()
{
// Arrange
var list1 = new WireMockList<string>("a", "b");
var list2 = new WireMockList<string>("a", "x");
// Act & Assert
list1.Equals(list2).Should().BeFalse();
}
[Fact]
public void WireMockListOfString_Equals_WhenListsHaveDifferentCounts_ShouldBeFalse()
{
// Arrange
var list1 = new WireMockList<string>("a", "b");
var list2 = new WireMockList<string>("a");
// Act & Assert
list1.Equals(list2).Should().BeFalse();
}
[Fact]
public void WireMockListOfString_Equals_WhenBothEmpty_ShouldBeTrue()
{
// Arrange
var list1 = new WireMockList<string>();
var list2 = new WireMockList<string>();
// Act & Assert
list1.Equals(list2).Should().BeTrue();
}
[Fact]
public void WireMockListOfString_Equals_WhenSameReference_ShouldBeTrue()
{
// Arrange
var list = new WireMockList<string>("a", "b");
var sameReference = list;
// Act & Assert
list.Equals(sameReference).Should().BeTrue();
}
[Fact]
public void WireMockListOfString_Equals_WhenComparedToNull_ShouldBeFalse()
{
// Arrange
var list = new WireMockList<string>("a");
// Act & Assert
list.Should().NotBeNull();
}
[Fact]
public void WireMockListOfString_Equals_WhenComparedToNonWireMockList_ShouldBeFalse()
{
// Arrange
var list = new WireMockList<string>("a");
// Act & Assert
list.Equals(new List<string> { "a" }).Should().BeFalse();
}
[Fact]
public void WireMockListOfString_GetHashCode_WhenListsHaveSameElements_ShouldBeEqual()
{
// Arrange
var list1 = new WireMockList<string>("a", "b", "c");
var list2 = new WireMockList<string>("a", "b", "c");
// Act & Assert
list1.GetHashCode().Should().Be(list2.GetHashCode());
}
[Fact]
public void WireMockListOfString_GetHashCode_WhenListsHaveDifferentElements_ShouldNotBeEqual()
{
// Arrange
var list1 = new WireMockList<string>("a", "b");
var list2 = new WireMockList<string>("x", "y");
// Act & Assert
list1.GetHashCode().Should().NotBe(list2.GetHashCode());
}
[Fact]
public void WireMockListOfString_GetHashCode_WhenEmpty_ShouldReturnConsistentValue()
{
// Arrange
var list1 = new WireMockList<string>();
var list2 = new WireMockList<string>();
// Act & Assert
list1.GetHashCode().Should().Be(list2.GetHashCode());
}
#endregion
}
@@ -1,9 +1,8 @@
// Copyright © WireMock.Net
using System.Net.Http;
using AnyOfTypes;
using WireMock.Extensions;
using WireMock.Matchers;
using WireMock.Models;
namespace WireMock.Net.Tests.Matchers;
@@ -12,59 +11,155 @@ public class FormUrlEncodedMatcherTest
private readonly CancellationToken _ct = TestContext.Current.CancellationToken;
[Theory]
[InlineData("*=*")]
[InlineData("name=John Doe")]
[InlineData("name=*")]
[InlineData("*=John Doe")]
[InlineData("email=johndoe@example.com")]
[InlineData("email=*")]
[InlineData("*=johndoe@example.com")]
[InlineData("name=John Doe", "email=johndoe@example.com")]
[InlineData("name=John Doe", "email=*")]
[InlineData("name=*", "email=*")]
[InlineData("*=John Doe", "*=johndoe@example.com")]
public async Task FormUrlEncodedMatcher_IsMatch(params string[] patterns)
[InlineData(true, "*=*")]
[InlineData(true, "name=John Doe")]
[InlineData(false, "name=Stef")]
[InlineData(false, "name=John Doe&name=Stef")]
[InlineData(true, "name=*")]
[InlineData(true, "*=John Doe")]
[InlineData(false, "*=Stef")]
[InlineData(false, "*=John Doe&*=Stef")]
[InlineData(true, "email=johndoe@example.com")]
[InlineData(true, "email=*")]
[InlineData(true, "*=johndoe@example.com")]
[InlineData(true, "name=John Doe", "email=johndoe@example.com")]
[InlineData(true, "name=John Doe", "email=*")]
[InlineData(true, "name=John Doe&name=Stef", "email=*")]
[InlineData(true, "name=Stef", "email=*")]
[InlineData(true, "name=*", "email=*")]
[InlineData(true, "*=John Doe", "*=johndoe@example.com")]
[InlineData(true, "*=Stef", "*=johndoe@example.com")]
[InlineData(true, "name=John Doe&name=Stef", "*=johndoe@example.com")]
public async Task FormUrlEncodedMatcher_IsMatch_Single_Or(bool expected, params string[] patterns)
{
// Arrange
var content = new FormUrlEncodedContent(
using var content = new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("name", "John Doe"),
new KeyValuePair<string, string>("email", "johndoe@example.com")
]);
var contentAsString = await content.ReadAsStringAsync(_ct);
var matcher = new FormUrlEncodedMatcher(patterns.Select(p => new AnyOf<string, StringPattern>(p)).ToArray());
var matcher = new FormUrlEncodedMatcher(patterns.ToAnyOfPatterns());
// Act
var score = matcher.IsMatch(contentAsString).IsPerfect();
// Assert
score.Should().BeTrue();
score.Should().Be(expected);
}
[Theory]
[InlineData(true, "*=*")]
[InlineData(false, "name=John Doe")]
[InlineData(false, "name=Stef")]
[InlineData(true, "name=John Doe&name=Stef")]
[InlineData(true, "name=*")]
[InlineData(false, "*=John Doe")]
[InlineData(false, "*=Stef")]
[InlineData(true, "*=John Doe&*=Stef")]
[InlineData(true, "email=johndoe@example.com")]
[InlineData(true, "email=*")]
[InlineData(true, "*=johndoe@example.com")]
[InlineData(true, "name=John Doe", "email=johndoe@example.com")]
[InlineData(true, "name=John Doe", "email=*")]
[InlineData(true, "name=John Doe&name=Stef", "email=*")]
[InlineData(true, "name=Stef", "email=*")]
[InlineData(true, "name=*", "email=*")]
[InlineData(true, "*=John Doe", "*=johndoe@example.com")]
[InlineData(true, "*=Stef", "*=johndoe@example.com")]
[InlineData(true, "name=John Doe&name=Stef", "*=johndoe@example.com")]
public async Task FormUrlEncodedMatcher_IsMatch_Multiple_Or(bool expected, params string[] patterns)
{
// Arrange
using var content = new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("name", "John Doe"),
new KeyValuePair<string, string>("name", "Stef"),
new KeyValuePair<string, string>("email", "johndoe@example.com")
]);
var contentAsString = await content.ReadAsStringAsync(_ct);
var matcher = new FormUrlEncodedMatcher(patterns.ToAnyOfPatterns());
// Act
var score = matcher.IsMatch(contentAsString).IsPerfect();
// Assert
score.Should().Be(expected);
}
[Theory]
[InlineData(true, "*=*")]
[InlineData(false, "name=John Doe")]
[InlineData(false, "name=Stef")]
[InlineData(false, "name=John Doe&name=Stef")]
[InlineData(false, "name=*")]
[InlineData(false, "*=John Doe")]
[InlineData(false, "*=Stef")]
[InlineData(false, "*=John Doe&*=Stef")]
[InlineData(false, "email=johndoe@example.com")]
[InlineData(false, "email=*")]
[InlineData(false, "*=johndoe@example.com")]
[InlineData(true, "name=John Doe", "email=johndoe@example.com")]
[InlineData(true, "name=John Doe", "email=*")]
[InlineData(false, "name=John Doe&name=Stef", "email=*")]
[InlineData(false, "name=Stef", "email=*")]
[InlineData(true, "name=*", "email=*")]
[InlineData(true, "*=John Doe", "*=johndoe@example.com")]
[InlineData(true, "*=*")]
public async Task FormUrlEncodedMatcher_IsMatch_And(bool expected, params string[] patterns)
[InlineData(false, "*=Stef", "*=johndoe@example.com")]
[InlineData(false, "name=John Doe&name=Stef", "*=johndoe@example.com")]
public async Task FormUrlEncodedMatcher_IsMatch_Single_And(bool expected, params string[] patterns)
{
// Arrange
var content = new FormUrlEncodedContent(
using var content = new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("name", "John Doe"),
new KeyValuePair<string, string>("email", "johndoe@example.com")
]);
var contentAsString = await content.ReadAsStringAsync(_ct);
var matcher = new FormUrlEncodedMatcher(patterns.Select(p => new AnyOf<string, StringPattern>(p)).ToArray(), true, MatchOperator.And);
var matcher = new FormUrlEncodedMatcher(patterns.ToAnyOfPatterns(), true, MatchOperator.And);
// Act
var score = matcher.IsMatch(contentAsString).IsPerfect();
// Assert
score.Should().Be(expected);
}
[Theory]
[InlineData(true, "*=*")]
[InlineData(false, "name=John Doe")]
[InlineData(false, "name=Stef")]
[InlineData(false, "name=John Doe&name=Stef")]
[InlineData(false, "name=*")]
[InlineData(false, "*=John Doe")]
[InlineData(false, "*=Stef")]
[InlineData(false, "*=John Doe&*=Stef")]
[InlineData(false, "email=johndoe@example.com")]
[InlineData(false, "email=*")]
[InlineData(false, "*=johndoe@example.com")]
[InlineData(false, "name=John Doe", "email=johndoe@example.com")]
[InlineData(false, "name=John Doe", "email=*")]
[InlineData(true, "name=John Doe&name=Stef", "email=*")]
[InlineData(false, "name=Stef", "email=*")]
[InlineData(true, "name=*", "email=*")]
[InlineData(false, "*=John Doe", "*=johndoe@example.com")]
[InlineData(false, "*=Stef", "*=johndoe@example.com")]
[InlineData(true, "name=John Doe&name=Stef", "*=johndoe@example.com")]
public async Task FormUrlEncodedMatcher_IsMatch_Multiple_And(bool expected, params string[] patterns)
{
// Arrange
using var content = new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("name", "John Doe"),
new KeyValuePair<string, string>("name", "Stef"),
new KeyValuePair<string, string>("email", "johndoe@example.com")
]);
var contentAsString = await content.ReadAsStringAsync(_ct);
var matcher = new FormUrlEncodedMatcher(patterns.ToAnyOfPatterns(), true, MatchOperator.And);
// Act
var score = matcher.IsMatch(contentAsString).IsPerfect();
@@ -74,12 +169,13 @@ public class FormUrlEncodedMatcherTest
}
[Fact]
public async Task FormUrlEncodedMatcher_IsMatch_And_MatchAllProperties()
public async Task FormUrlEncodedMatcher_IsMatch_And_MatchAllProperties_MissingRequiredKey_ShouldNotMatch()
{
// Arrange
var content = new FormUrlEncodedContent(
using var content = new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("name", "John Doe"),
new KeyValuePair<string, string>("name", "Stef"),
new KeyValuePair<string, string>("email", "johndoe@example.com")
]);
var contentAsString = await content.ReadAsStringAsync(_ct);
@@ -93,4 +189,25 @@ public class FormUrlEncodedMatcherTest
// Assert
score.Should().BeFalse();
}
[Fact]
public async Task FormUrlEncodedMatcher_IsMatch_And_MatchAllProperties_ConflictingEmailPatterns_ShouldNotMatch()
{
// Arrange
using var content = new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("name", "John Doe"),
new KeyValuePair<string, string>("name", "Stef"),
new KeyValuePair<string, string>("email", "johndoe@example.com")
]);
var contentAsString = await content.ReadAsStringAsync(_ct);
var matcher = new FormUrlEncodedMatcher(["name=*", "email=*", "email=x"], matchOperator: MatchOperator.And);
// Act
var score = matcher.IsMatch(contentAsString).IsPerfect();
// Assert
score.Should().BeFalse();
}
}
@@ -142,12 +142,12 @@ public class RequestBuilderWithBodyTests
public void Request_WithBody_FuncFormUrlEncoded()
{
// Assign
var requestBuilder = Request.Create().UsingAnyMethod().WithBody((IDictionary<string, string>? values) => values != null);
var requestBuilder = Request.Create().UsingAnyMethod().WithBody((IDictionary<string, WireMockList<string>>? values) => values != null);
// Act
var body = new BodyData
{
BodyAsFormUrlEncoded = new Dictionary<string, string>(),
BodyAsFormUrlEncoded = new Dictionary<string, WireMockList<string>>(),
DetectedBodyTypeFromContentType = BodyType.FormUrlEncoded,
DetectedBodyType = BodyType.FormUrlEncoded
};
@@ -15,7 +15,7 @@ public class RequestMessageParamMatcherTests
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "KeY", true, new[] { "test1" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "KeY", true, ["test1"]);
// Act
var result = new RequestMatchResult();
@@ -30,7 +30,7 @@ public class RequestMessageParamMatcherTests
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "test1", "test2" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, ["test1", "test2"]);
// Act
var result = new RequestMatchResult();
@@ -60,7 +60,7 @@ public class RequestMessageParamMatcherTests
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1,test2,test3"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new IStringMatcher[] { new ExactMatcher("test1", "test2") });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, [new ExactMatcher("test1", "test2")]);
// Act
var result = new RequestMatchResult();
@@ -71,18 +71,18 @@ public class RequestMessageParamMatcherTests
}
[Fact]
public void RequestMessageParamMatcher_GetMatchingScore_KeyWith2ValuesPresentInUrl_And_With1ExactStringWith3Patterns_Returns0_66()
public void RequestMessageParamMatcher_GetMatchingScore_KeyWith2ValuesPresentInUrl_And_With1ExactStringWith3Patterns_Returns1_0()
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new IStringMatcher[] { new ExactMatcher("test1", "test2", "test3") });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, [new ExactMatcher("test1", "test2", "test3")]);
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
score.Should().BeApproximately(0.66d, 0.1d);
score.Should().Be(1.0d);
}
[Fact]
@@ -90,7 +90,7 @@ public class RequestMessageParamMatcherTests
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "test1", "test2" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, ["test1", "test2"]);
// Act
var result = new RequestMatchResult();
@@ -105,7 +105,7 @@ public class RequestMessageParamMatcherTests
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new IStringMatcher[] { new ExactMatcher("test1"), new ExactMatcher("test2") });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, [new ExactMatcher("test1"), new ExactMatcher("test2")]);
// Act
var result = new RequestMatchResult();
@@ -120,7 +120,7 @@ public class RequestMessageParamMatcherTests
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=test0,test2"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "test1", "test2" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, ["test1", "test2"]);
// Act
var result = new RequestMatchResult();
@@ -135,7 +135,7 @@ public class RequestMessageParamMatcherTests
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "test1", "test2" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, ["test1", "test2"]);
// Act
var result = new RequestMatchResult();
@@ -215,7 +215,7 @@ public class RequestMessageParamMatcherTests
{
// Assign: the param value in the URL matches the reject pattern -> the mapping must be rejected (score 0.0).
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=abc"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.RejectOnMatch, "key", false, new[] { "abc" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.RejectOnMatch, "key", false, ["abc"]);
// Act
var result = new RequestMatchResult();
@@ -230,7 +230,7 @@ public class RequestMessageParamMatcherTests
{
// Assign: the param value in the URL does NOT match the reject pattern -> the mapping is accepted (score 1.0).
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=xyz"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.RejectOnMatch, "key", false, new[] { "abc" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.RejectOnMatch, "key", false, ["abc"]);
// Act
var result = new RequestMatchResult();
@@ -245,7 +245,7 @@ public class RequestMessageParamMatcherTests
{
// Assign: ignoreCase must still be honored on the inner matcher after the fix.
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=ABC"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.RejectOnMatch, "key", true, new[] { "abc" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.RejectOnMatch, "key", true, ["abc"]);
// Act
var result = new RequestMatchResult();
@@ -260,7 +260,7 @@ public class RequestMessageParamMatcherTests
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=abc"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "abc" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, ["abc"]);
// Act
var result = new RequestMatchResult();
@@ -275,7 +275,7 @@ public class RequestMessageParamMatcherTests
{
// Assign
var requestMessage = new RequestMessage(new UrlDetails("http://localhost?key=xyz"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, new[] { "abc" });
var matcher = new RequestMessageParamMatcher(MatchBehaviour.AcceptOnMatch, "key", false, ["abc"]);
// Act
var result = new RequestMatchResult();
@@ -7,27 +7,27 @@ namespace WireMock.Net.Tests.Util;
public class QueryStringParserTests
{
public static IEnumerable<object?[]> QueryStringTestData => new List<object?[]>
public static List<object?[]> QueryStringTestData => new()
{
new object?[] { null, false, false, null },
new object?[] { string.Empty, false, true, new Dictionary<string, string>() },
new object?[] { "test", false, true, new Dictionary<string, string>() },
new object?[] { "&", false, true, new Dictionary<string, string>() },
new object?[] { "&&", false, true, new Dictionary<string, string>() },
new object?[] { "a=", false, true, new Dictionary<string, string> { { "a", "" } } },
new object?[] { "&a", false, true, new Dictionary<string, string>() },
new object?[] { "&a=", false, true, new Dictionary<string, string> { { "a", "" } } },
new object?[] { "&key1=value1", false, true, new Dictionary<string, string> { { "key1", "value1" } } },
new object?[] { "key1=value1", false, true, new Dictionary<string, string> { { "key1", "value1" } } },
new object?[] { "key1=value1&key2=value2", false, true, new Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } } },
new object?[] { "key1=value1&key2=value2&", false, true, new Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } } },
new object?[] { "key1=value1&&key2=value2", false, true, new Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } } },
new object?[] { "&key1=value1&key2=value2&&", false, true, new Dictionary<string, string> { { "key1", "value1" }, { "key2", "value2" } } },
new object?[] { string.Empty, false, true, new Dictionary<string, WireMockList<string>>() },
new object?[] { "test", false, true, new Dictionary<string, WireMockList<string>>() },
new object?[] { "&", false, true, new Dictionary<string, WireMockList<string>>() },
new object?[] { "&&", false, true, new Dictionary<string, WireMockList<string>>() },
new object?[] { "a=", false, true, new Dictionary<string, WireMockList<string>> { { "a", new WireMockList<string>("") } } },
new object?[] { "&a", false, true, new Dictionary<string, WireMockList<string>>() },
new object?[] { "&a=", false, true, new Dictionary<string, WireMockList<string>> { { "a", new WireMockList<string>("") } } },
new object?[] { "&key1=value1", false, true, new Dictionary<string, WireMockList<string>> { { "key1", new WireMockList<string>("value1") } } },
new object?[] { "key1=value1", false, true, new Dictionary<string, WireMockList<string>> { { "key1", new WireMockList<string>("value1") } } },
new object?[] { "key1=value1&key2=value2", false, true, new Dictionary<string, WireMockList<string>> { { "key1", new WireMockList<string>("value1") }, { "key2", new WireMockList<string>("value2") } } },
new object?[] { "key1=value1&key2=value2&", false, true, new Dictionary<string, WireMockList<string>> { { "key1", new WireMockList<string>("value1") }, { "key2", new WireMockList<string>("value2") } } },
new object?[] { "key1=value1&&key2=value2", false, true, new Dictionary<string, WireMockList<string>> { { "key1", new WireMockList<string>("value1") }, { "key2", new WireMockList<string>("value2") } } },
new object?[] { "&key1=value1&key2=value2&&", false, true, new Dictionary<string, WireMockList<string>> { { "key1", new WireMockList<string>("value1") }, { "key2", new WireMockList<string>("value2") } } },
};
[Theory]
[MemberData(nameof(QueryStringTestData))]
public void TryParse_Should_Parse_QueryString(string queryString, bool caseIgnore, bool expectedResult, IDictionary<string, string> expectedOutput)
public void TryParse_Should_Parse_QueryString(string queryString, bool caseIgnore, bool expectedResult, IDictionary<string, WireMockList<string>> expectedOutput)
{
// Act
var result = QueryStringParser.TryParse(queryString, caseIgnore, out var actual);
@@ -49,7 +49,7 @@ public class QueryStringParserTests
// Assert
result.Should().BeTrue();
actual.Should().BeEquivalentTo(new Dictionary<string, string> { { "x", "rNaCP7hv8UOmS/JcujdvLw==" } });
actual.Should().BeEquivalentTo(new Dictionary<string, WireMockList<string>> { { "x", new WireMockList<string>("rNaCP7hv8UOmS/JcujdvLw==") } });
}
[Fact]
@@ -12,6 +12,7 @@ using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using WireMock.Settings;
using WireMock.Types;
namespace WireMock.Net.Tests;
@@ -339,7 +340,7 @@ public partial class WireMockServerTests
#endif
[Fact]
public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithFunc()
public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithFunc1()
{
// Arrange
using var server = WireMockServer.Start();
@@ -354,8 +355,36 @@ public partial class WireMockServerTests
);
// Act
var content = new FormUrlEncodedContent([new KeyValuePair<string, string>("key1", "value1")]);
var response = await new HttpClient()
using var content = new FormUrlEncodedContent([new KeyValuePair<string, string>("key1", "value1")]);
using var httpClient = new HttpClient();
var response = await httpClient
.PostAsync($"{server.Url}/foo", content, _ct);
// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
server.Stop();
}
[Fact]
public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithFunc2()
{
// Arrange
using var server = WireMockServer.Start();
server.Given(
Request.Create()
.UsingPost()
.WithPath("/foo")
.WithBody((IDictionary<string, WireMockList<string>>? values) => values != null && values.TryGetValue("key1", out var v) && v == "value1")
)
.RespondWith(
Response.Create()
);
// Act
using var content = new FormUrlEncodedContent([new KeyValuePair<string, string>("key1", "value1")]);
using var httpClient = new HttpClient();
var response = await httpClient
.PostAsync($"{server.Url}/foo", content, _ct);
// Assert
@@ -382,7 +411,7 @@ public partial class WireMockServerTests
);
// Act
var content = new FormUrlEncodedContent(
using var content = new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("name", "John Doe"),
new KeyValuePair<string, string>("email", "johndoe@example.com")
@@ -400,7 +429,7 @@ public partial class WireMockServerTests
public async Task WireMockServer_WithBodyAsFormUrlEncoded_Using_PostAsync_And_WithFormUrlEncodedMatcher()
{
// Arrange
var matcher = new FormUrlEncodedMatcher(["email=johndoe@example.com", "name=John Doe"]);
var matcher = new FormUrlEncodedMatcher(["email=johndoe@example.com", "name=John*"]);
using var server = WireMockServer.Start();
server.Given(
Request.Create()
@@ -425,7 +454,7 @@ public partial class WireMockServerTests
);
// Act 1
var contentOrdered = new FormUrlEncodedContent(
using var contentOrdered = new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("name", "John Doe"),
new KeyValuePair<string, string>("email", "johndoe@example.com")
@@ -439,7 +468,7 @@ public partial class WireMockServerTests
// Act 2
var contentUnordered = new FormUrlEncodedContent(
using var contentUnordered = new FormUrlEncodedContent(
[
new KeyValuePair<string, string>("email", "johndoe@example.com"),
new KeyValuePair<string, string>("name", "John Doe"),
@@ -447,7 +476,6 @@ public partial class WireMockServerTests
var responseUnordered = await new HttpClient()
.PostAsync($"{server.Url}/bar", contentUnordered, _ct)
;
// Assert 2
responseUnordered.StatusCode.Should().Be(HttpStatusCode.OK);