Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: avoid null exception when received body is empty but recorded body isn't #59

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
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 CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

- Add .NET 8.0 support
- `AdvancedSettings` uses `MatchRules.Default` instead of a new instance of `MatchRules` if not provided during construction
- Fix `NullReferenceException` when trying to match by body with a null body (`refit` compatibility)

## v0.9.0 (2023-05-17)

Expand Down
20 changes: 20 additions & 0 deletions EasyVCR.Tests/ClientTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -513,6 +513,26 @@ public async Task TestMatchNonJsonBody()
Assert.IsNotNull(response);
}

[TestMethod]
public async Task TestMatchEmptyStringBodyToNonEmptyStringBody()
{
var cassette = TestUtils.GetCassette("test_match_empty_body");
cassette.Erase(); // Erase cassette before recording

const string url = "https://httpbin.org/post";

var client = HttpClients.NewHttpClient(cassette, Mode.Record);
var someContent = new ByteArrayContent(Encoding.UTF8.GetBytes("non_empty_string_body"));
_ = await client.PostAsync(url, someContent);

// try to replay the request with match by body enforcement
client = HttpClients.NewHttpClient(cassette, Mode.Replay, new AdvancedSettings
{
MatchRules = new MatchRules().ByBody()
});
var emptyContent = new ByteArrayContent(Encoding.UTF8.GetBytes(string.Empty));
await Assert.ThrowsExceptionAsync<VCRException>(async () => await client.PostAsync(url, emptyContent), $"No interaction found for request POST {url}");
}

[TestMethod]
public async Task TestInteractionElements()
Expand Down
7 changes: 7 additions & 0 deletions EasyVCR/InternalUtilities/Extensions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
namespace EasyVCR.InternalUtilities
{
public static class Extensions
{
public static bool IsEmptyStringOrNull(this string? str) => str == null || string.IsNullOrWhiteSpace(str);
}
}
18 changes: 16 additions & 2 deletions EasyVCR/MatchRules.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Web;
using EasyVCR.InternalUtilities;
using EasyVCR.RequestElements;
using JsonSerialization = EasyVCR.InternalUtilities.JSON.Serialization;
using XmlSerialization = EasyVCR.InternalUtilities.XML.Serialization;
Expand Down Expand Up @@ -132,7 +133,7 @@ public MatchRules ByBody(List<CensorElement>? ignoredElements = null)
return true;

if (received.Body == null || recorded.Body == null)
// one has a null body, so they don't match
// one has a null body, the other does not, so they don't match
return false;

var receivedBody = received.Body;
Expand All @@ -155,11 +156,24 @@ public MatchRules ByBody(List<CensorElement>? ignoredElements = null)
// not JSON, using the string as it is
}

if (receivedBody.IsEmptyStringOrNull())
// short-cut if the received body is empty
receivedBody = null;

if (recordedBody.IsEmptyStringOrNull())
// short-cut if the recorded body is empty
recordedBody = null;

if (receivedBody == null && recordedBody == null)
// both have empty string bodies, so they match
return true;

return receivedBody!.Equals(recordedBody, StringComparison.OrdinalIgnoreCase);
if (receivedBody == null || recordedBody == null)
// one has a null body, the other does not, so they don't match
return false;

// if the bodies are not null, then we can compare them
return receivedBody.Equals(recordedBody, StringComparison.OrdinalIgnoreCase);
});
return this;
}
Expand Down
Loading