diff --git a/Test/Flurl.Test.Shared/Http/TestingTests.cs b/Test/Flurl.Test.Shared/Http/TestingTests.cs
index 4bd5b757..568a16d1 100644
--- a/Test/Flurl.Test.Shared/Http/TestingTests.cs
+++ b/Test/Flurl.Test.Shared/Http/TestingTests.cs
@@ -65,6 +65,15 @@ public async Task can_setup_multiple_responses() {
HttpTest.ShouldNotHaveCalled("http://www.otherapi.com/*");
}
+ [Test]
+ public async Task can_assert_query_params() {
+ await "http://www.api.com?x=111&y=222&z=333".GetAsync();
+ HttpTest.ShouldHaveCalled("http://www.api.com*").WithQueryParam("x");
+ HttpTest.ShouldHaveCalled("http://www.api.com*").WithQueryParam("y", 222);
+ HttpTest.ShouldHaveCalled("*").WithQueryParam("z", "*3");
+ HttpTest.ShouldHaveCalled("*").WithQueryParams(new { z = 333, y = 222 });
+ }
+
[Test]
public async Task can_simulate_timeout() {
HttpTest.SimulateTimeout();
diff --git a/src/Flurl.Http.Shared/Testing/HttpCallAssertion.cs b/src/Flurl.Http.Shared/Testing/HttpCallAssertion.cs
index a1dc9012..6a94e64d 100644
--- a/src/Flurl.Http.Shared/Testing/HttpCallAssertion.cs
+++ b/src/Flurl.Http.Shared/Testing/HttpCallAssertion.cs
@@ -4,6 +4,7 @@
using System.Net.Http;
using System.Text;
using System.Text.RegularExpressions;
+using Flurl.Util;
namespace Flurl.Http.Testing
{
@@ -45,7 +46,40 @@ public void Times(int expectedCount) {
/// Can contain * wildcard.
public HttpCallAssertion WithUrlPattern(string urlPattern) {
_urlPattern = urlPattern; // this will land in the exception message when we assert, which is the only reason for capturing it
- return With(c => MatchesPattern(c.Request.RequestUri.AbsoluteUri, urlPattern));
+ return With(c => MatchesPattern(c.Url, urlPattern));
+ }
+
+ ///
+ /// Asserts whether calls were made containing the given query parameter (regardless of its value).
+ ///
+ /// The query parameter name.
+ ///
+ public HttpCallAssertion WithQueryParam(string name) {
+ return With(c => new Url(c.Url).QueryParams.Any(q => q.Name == name));
+ }
+
+ ///
+ /// Asserts whether calls were made containing the given query parameter name/value.
+ ///
+ /// The query parameter name.
+ /// The query parameter value. Can contain * wildcard.
+ ///
+ public HttpCallAssertion WithQueryParam(string name, object value) {
+ return With(c => new Url(c.Url).QueryParams.Any(q => q.Name == name && MatchesPattern(q.Value.ToString(), value.ToString())));
+ }
+
+ ///
+ /// Asserts whether calls were made containing all of the given query parameters.
+ ///
+ /// Object (usually anonymous) or dictionary that is parsed to name/value query parameters to check for.
+ ///
+ public HttpCallAssertion WithQueryParams(object values) {
+ return With(c => {
+ var expected = values.ToKeyValuePairs().Select(kv => $"{kv.Key}={kv.Value}");
+ var actual = new Url(c.Url).QueryParams.Select(q => $"{q.Name}={q.Value}");
+ //http://stackoverflow.com/a/333034/62600
+ return !expected.Except(actual).Any();
+ });
}
///
diff --git a/src/Flurl.Http.Shared/Testing/HttpTest.cs b/src/Flurl.Http.Shared/Testing/HttpTest.cs
index 69aabb5b..25e93ebe 100644
--- a/src/Flurl.Http.Shared/Testing/HttpTest.cs
+++ b/src/Flurl.Http.Shared/Testing/HttpTest.cs
@@ -120,8 +120,8 @@ public HttpCallAssertion ShouldHaveCalled(string urlPattern) {
/// Throws an HttpCallAssertException if a URL matching the given pattern was called.
///
/// URL that should not have been called. Can include * wildcard character.
- public HttpCallAssertion ShouldNotHaveCalled(string urlPattern) {
- return new HttpCallAssertion(CallLog, true).WithUrlPattern(urlPattern);
+ public void ShouldNotHaveCalled(string urlPattern) {
+ new HttpCallAssertion(CallLog, true).WithUrlPattern(urlPattern);
}
///