Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Source/Mockolate/MockRegistration.Setup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -307,6 +307,7 @@ public ValueStorage GetOrAdd(NamedParameterValue key, Func<ValueStorage> valueGe
}
}

[ExcludeFromCodeCoverage]
private sealed class NamedParameterValueComparer : IEqualityComparer<NamedParameterValue>
{
public static readonly NamedParameterValueComparer Instance = new();
Expand Down
6 changes: 1 addition & 5 deletions Source/Mockolate/Web/HttpClientExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -83,12 +83,8 @@ public bool Matches(HttpRequestMessage value)
}

string requestUri1 = value.RequestUri.ToString();
string requestUri2 = requestUri1.EndsWith('/')
? requestUri1.Substring(0, requestUri1.Length - 1)
: requestUri1 + '/';

return invokableParameter.Matches(requestUri1) ||
invokableParameter.Matches(requestUri2);
(requestUri1.EndsWith('/') && invokableParameter.Matches(requestUri1.TrimEnd('/')));
}

public void InvokeCallbacks(HttpRequestMessage value)
Expand Down
5 changes: 1 addition & 4 deletions Source/Mockolate/Web/ItExtensions.Uri.cs
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,9 @@ public bool Matches(object? value)
if (pattern is not null)
{
string requestUri1 = uri.ToString();
string requestUri2 = requestUri1.EndsWith('/')
? requestUri1.Substring(0, requestUri1.Length - 1)
: requestUri1 + '/';
Wildcard wildcard = Wildcard.Pattern(pattern, true);
if (!wildcard.Matches(requestUri1) &&
!wildcard.Matches(requestUri2))
(!requestUri1.EndsWith('/') || !wildcard.Matches(requestUri1.TrimEnd('/'))))
{
return false;
}
Expand Down
27 changes: 19 additions & 8 deletions Tests/Mockolate.Tests/MockMethods/VerifyInvokedTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,25 +17,25 @@ public async Task Equals_ShouldWork()
}

[Fact]
public async Task Equals_WithOtherOverload_ShouldWork()
public async Task Equals_ShouldWorkWithNull()
{
object obj = new();
object? obj = null;
IMethodService mock = Mock.Create<IMethodService>();

_ = mock.Equals(3);
_ = mock.Equals(null);

await That(mock.VerifyMock.Invoked.Equals(It.Is(obj))).Never();
await That(mock.VerifyMock.Invoked.Equals(It.Is(obj))).Once();
}

[Fact]
public async Task Equals_ShouldWorkWithNull()
public async Task Equals_WithOtherOverload_ShouldWork()
{
object? obj = null;
object obj = new();
IMethodService mock = Mock.Create<IMethodService>();

_ = mock.Equals(null);
_ = mock.Equals(3);

await That(mock.VerifyMock.Invoked.Equals(It.Is(obj))).Once();
await That(mock.VerifyMock.Invoked.Equals(It.Is(obj))).Never();
}

[Fact]
Expand All @@ -59,6 +59,17 @@ public async Task MethodWithDifferentName_ShouldNotMatch()
await That(sut.VerifyMock.Invoked.Subtract(It.IsAny<int>(), It.IsAny<int?>())).Never();
}

[Fact]
public async Task MethodWithDifferentName_WithParameters_ShouldNotMatch()
{
MockTests.IMyService sut = Mock.Create<MockTests.IMyService>();

sut.Subtract(1, 4);
sut.Subtract(2, 4);

await That(sut.VerifyMock.Invoked.Multiply(Match.AnyParameters())).Never();
}

[Fact]
public async Task MethodWithDifferentOverload_ShouldNotMatch()
{
Expand Down
50 changes: 50 additions & 0 deletions Tests/Mockolate.Tests/Web/HttpClientExtensionsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,24 @@ namespace Mockolate.Tests.Web;

public sealed partial class HttpClientExtensionsTests
{
[Fact]
public async Task Callback_ShouldBeInvoked()
{
HttpClient httpClient = Mock.Create<HttpClient>();
httpClient.SetupMock.Method
.GetAsync(It.Matches("*").Monitor(out IParameterMonitor<string> monitor))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));

await httpClient.GetAsync("https://www.aweXpect.com/foo", CancellationToken.None);
await httpClient.PostAsync("https://www.aweXpect.com/bar", null, CancellationToken.None);
await httpClient.GetAsync("https://www.aweXpect.com/baz", CancellationToken.None);

await That(monitor.Values).IsEqualTo([
"https://www.awexpect.com/foo",
"https://www.awexpect.com/baz",
]);
}

[Fact]
public async Task InvalidParameter_ShouldReturnTrue()
{
Expand Down Expand Up @@ -48,6 +66,38 @@ public async Task NullUri_ShouldReturnFalse()
await That(result).IsFalse();
}

[Theory]
[InlineData("*aweXpect.com")]
[InlineData("*aweXpect.com/")]
public async Task TrailingSlash_ShouldBeIgnored(string matchPattern)
{
HttpClient httpClient = Mock.Create<HttpClient>();
httpClient.SetupMock.Method
.GetAsync(It.Matches(matchPattern))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));

HttpResponseMessage result =
await httpClient.GetAsync("https://www.aweXpect.com", CancellationToken.None);

await That(result.StatusCode)
.IsEqualTo(HttpStatusCode.OK);
}

[Fact]
public async Task TrailingSlash_WhenNotPresent_ShouldNotBeAdded()
{
HttpClient httpClient = Mock.Create<HttpClient>();
httpClient.SetupMock.Method
.GetAsync(It.Matches("*www.aweXpect.com/foo/"))
.ReturnsAsync(new HttpResponseMessage(HttpStatusCode.OK));

HttpResponseMessage result =
await httpClient.GetAsync("https://www.aweXpect.com/foo", CancellationToken.None);

await That(result.StatusCode)
.IsEqualTo(HttpStatusCode.NotImplemented);
}

private sealed class InvalidParameter : IParameter<string?>
{
public IParameter<string?> Do(Action<string?> callback)
Expand Down
120 changes: 104 additions & 16 deletions Tests/Mockolate.Tests/Web/ItExtensionsTests.IsBinaryContentTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,76 @@ public sealed class IsBinaryContentTests
{
[Theory]
[InlineData(new byte[0], new byte[0], true)]
[InlineData(new byte[] { 0x1, }, new byte[] { 0x1, }, true)]
[InlineData(new byte[] { 0x1, }, new byte[] { 0x2, }, false)]
[InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, }, true)]
[InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x2, }, true)]
[InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x3, }, true)]
[InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, 0x2, }, true)]
[InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x2, 0x3, }, true)]
[InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, 0x3, }, false)]
[InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, 0x2, 0x3, }, true)]
[InlineData(new byte[] { 0x1, 0x2, 0x3, }, new byte[] { 0x1, 0x2, 0x3, 0x4, }, false)]
[InlineData(new byte[]
{
0x1,
}, new byte[]
{
0x1,
}, true)]
[InlineData(new byte[]
{
0x1,
}, new byte[]
{
0x2,
}, false)]
[InlineData(new byte[]
{
0x1, 0x2, 0x3,
}, new byte[]
{
0x1,
}, true)]
[InlineData(new byte[]
{
0x1, 0x2, 0x3,
}, new byte[]
{
0x2,
}, true)]
[InlineData(new byte[]
{
0x1, 0x2, 0x3,
}, new byte[]
{
0x3,
}, true)]
[InlineData(new byte[]
{
0x1, 0x2, 0x3,
}, new byte[]
{
0x1, 0x2,
}, true)]
[InlineData(new byte[]
{
0x1, 0x2, 0x3,
}, new byte[]
{
0x2, 0x3,
}, true)]
[InlineData(new byte[]
{
0x1, 0x2, 0x3,
}, new byte[]
{
0x1, 0x3,
}, false)]
[InlineData(new byte[]
{
0x1, 0x2, 0x3,
}, new byte[]
{
0x1, 0x2, 0x3,
}, true)]
[InlineData(new byte[]
{
0x1, 0x2, 0x3,
}, new byte[]
{
0x1, 0x2, 0x3, 0x4,
}, false)]
public async Task Containing_ShouldCheckForEquality(byte[] body, byte[] expected, bool expectSuccess)
{
HttpClient httpClient = Mock.Create<HttpClient>();
Expand All @@ -41,10 +101,34 @@ public async Task Containing_ShouldCheckForEquality(byte[] body, byte[] expected

[Theory]
[InlineData(new byte[0], new byte[0], true)]
[InlineData(new byte[] { 0x66, }, new byte[] { 0x66, }, true)]
[InlineData(new byte[] { 0x66, }, new byte[] { 0x67, }, false)]
[InlineData(new byte[] { 0x66, 0x67, }, new byte[] { 0x67, }, false)]
[InlineData(new byte[] { 0x66, 0x67, }, new byte[] { 0x67, 0x68, 0x69, }, false)]
[InlineData(new byte[]
{
0x66,
}, new byte[]
{
0x66,
}, true)]
[InlineData(new byte[]
{
0x66,
}, new byte[]
{
0x67,
}, false)]
[InlineData(new byte[]
{
0x66, 0x67,
}, new byte[]
{
0x67,
}, false)]
[InlineData(new byte[]
{
0x66, 0x67,
}, new byte[]
{
0x67, 0x68, 0x69,
}, false)]
public async Task EqualTo_ShouldCheckForEquality(byte[] body, byte[] expected, bool expectSuccess)
{
HttpClient httpClient = Mock.Create<HttpClient>();
Expand All @@ -58,11 +142,12 @@ public async Task EqualTo_ShouldCheckForEquality(byte[] body, byte[] expected, b

await That(result.StatusCode).IsEqualTo(expectSuccess ? HttpStatusCode.OK : HttpStatusCode.NotImplemented);
}

#if !NETFRAMEWORK
[Fact]
public async Task ShouldSupportMonitoring()
{
int callbackCount = 0;
List<ByteArrayContent> responses =
[
new([]),
Expand All @@ -71,7 +156,9 @@ public async Task ShouldSupportMonitoring()
];
HttpClient httpClient = Mock.Create<HttpClient>();
httpClient.SetupMock.Method.PostAsync(It.IsAny<Uri>(),
It.IsBinaryContent().Monitor(out IParameterMonitor<HttpContent?> monitor));
It.IsBinaryContent()
.Do(_ => callbackCount++)
.Monitor(out IParameterMonitor<HttpContent?> monitor));

foreach (ByteArrayContent response in responses)
{
Expand All @@ -81,6 +168,7 @@ public async Task ShouldSupportMonitoring()
await That(
(await Task.WhenAll(monitor.Values.Select(c => c!.ReadAsByteArrayAsync()))).Select(x => x.Length))
.IsEqualTo([0, 1, 3,]);
await That(callbackCount).IsEqualTo(3);
}
#endif

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public sealed class IsStringContentTests
[Fact]
public async Task ShouldSupportMonitoring()
{
int callbackCount = 0;
List<StringContent> responses =
[
new("", Encoding.UTF8, "application/json"),
Expand All @@ -26,7 +27,9 @@ public async Task ShouldSupportMonitoring()
];
HttpClient httpClient = Mock.Create<HttpClient>();
httpClient.SetupMock.Method.PostAsync(It.IsAny<Uri>(),
It.IsStringContent("application/json").Monitor(out IParameterMonitor<HttpContent?> monitor));
It.IsStringContent("application/json")
.Do(_ => callbackCount++)
.Monitor(out IParameterMonitor<HttpContent?> monitor));

foreach (StringContent response in responses)
{
Expand All @@ -35,6 +38,7 @@ public async Task ShouldSupportMonitoring()

await That(await Task.WhenAll(monitor.Values.Select(c => c!.ReadAsStringAsync())))
.IsEqualTo(["", "foo", "bar",]);
await That(callbackCount).IsEqualTo(3);
}
#endif

Expand Down
Loading
Loading