Skip to content
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
Original file line number Diff line number Diff line change
Expand Up @@ -126,6 +126,7 @@ namespace Mockly
public Mockly.RequestMockResponseBuilder RespondsWithODataResult<T>(System.Net.HttpStatusCode statusCode, System.Collections.Generic.IEnumerable<Mockly.IResponseBuilder<T>> builders) { }
public Mockly.RequestMockResponseBuilder RespondsWithODataResult<T>(System.Net.HttpStatusCode statusCode, System.Collections.Generic.IEnumerable<Mockly.IResponseBuilder<T>> builders, string odataContext) { }
public Mockly.RequestMockResponseBuilder RespondsWithStatus(System.Net.HttpStatusCode statusCode) { }
public Mockly.RequestMockBuilder Using(System.Text.Json.JsonSerializerOptions options) { }
public Mockly.RequestMockBuilder With(System.Func<Mockly.RequestInfo, System.Threading.Tasks.Task<bool>> matcher, [System.Runtime.CompilerServices.CallerArgumentExpression("matcher")] string? matcherText = null) { }
public Mockly.RequestMockBuilder With(System.Func<Mockly.RequestInfo, bool> matcher, [System.Runtime.CompilerServices.CallerArgumentExpression("matcher")] string? matcherText = null) { }
public Mockly.RequestMockBuilder WithAnyQuery() { }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,7 @@ namespace Mockly
public Mockly.RequestMockResponseBuilder RespondsWithODataResult<T>(System.Net.HttpStatusCode statusCode, System.Collections.Generic.IEnumerable<Mockly.IResponseBuilder<T>> builders) { }
public Mockly.RequestMockResponseBuilder RespondsWithODataResult<T>(System.Net.HttpStatusCode statusCode, System.Collections.Generic.IEnumerable<Mockly.IResponseBuilder<T>> builders, string odataContext) { }
public Mockly.RequestMockResponseBuilder RespondsWithStatus(System.Net.HttpStatusCode statusCode) { }
public Mockly.RequestMockBuilder Using(System.Text.Json.JsonSerializerOptions options) { }
public Mockly.RequestMockBuilder With(System.Func<Mockly.RequestInfo, System.Threading.Tasks.Task<bool>> matcher, [System.Runtime.CompilerServices.CallerArgumentExpression("matcher")] string? matcherText = null) { }
public Mockly.RequestMockBuilder With(System.Func<Mockly.RequestInfo, bool> matcher, [System.Runtime.CompilerServices.CallerArgumentExpression("matcher")] string? matcherText = null) { }
public Mockly.RequestMockBuilder WithAnyQuery() { }
Expand Down
57 changes: 57 additions & 0 deletions Mockly.Specs/HttpMockSpecs.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using System.Net.Http;
using System.Net.Http.Headers;
using System.Text;
using System.Text.Json;
using System.Threading.Tasks;
using FluentAssertions;
using Xunit;
Expand Down Expand Up @@ -2087,4 +2088,60 @@ await response.Should().BeEquivalentTo(new
});
}
}

public class WhenUsingCustomJsonSerializerOptions
{
[Fact]
public async Task Can_use_custom_options_for_json_response_content()
{
// Arrange
var mock = new HttpMock();

var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};

mock.ForGet()
.WithPath("/api/data")
.Using(options)
.RespondsWithJsonContent(new { UserId = 42, UserName = "Alice" });

// Act
var response = await mock.GetClient().GetAsync("https://localhost/api/data");
var body = await response.Content.ReadAsStringAsync();

// Assert
response.StatusCode.Should().Be(HttpStatusCode.OK);
body.Should().Contain("\"userId\"").And.Contain("\"userName\"");
body.Should().NotContain("\"UserId\"").And.NotContain("\"UserName\"");
}

[Fact]
public async Task Can_use_custom_options_to_match_request_body_as_object()
{
// Arrange
var mock = new HttpMock();

var options = new JsonSerializerOptions
{
PropertyNamingPolicy = JsonNamingPolicy.CamelCase
};

mock.ForPost()
.WithPath("/api/data")
.Using(options)
.WithBody(new { UserId = 42, UserName = "Alice" })
.RespondsWithStatus(HttpStatusCode.NoContent);

var client = mock.GetClient();

// Act: Send camelCase JSON (matching what camelCase options would serialize to)
var response = await client.PostAsync("https://localhost/api/data",
new StringContent("{\"userId\":42,\"userName\":\"Alice\"}"));

// Assert
response.StatusCode.Should().Be(HttpStatusCode.NoContent);
}
}
}
30 changes: 26 additions & 4 deletions Mockly/RequestMockBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
private string? scheme = "https";
private string? hostPattern = "localhost";
private RequestCollection? requestCollection;
private JsonSerializerOptions? jsonSerializerOptions;

internal RequestMockBuilder(HttpMock mockBuilder, HttpMethod method)
{
Expand Down Expand Up @@ -194,7 +195,7 @@
throw new ArgumentNullException(nameof(body));
}

var json = JsonSerializer.Serialize(body);
var json = JsonSerializer.Serialize(body, jsonSerializerOptions);
return WithBodyMatchingJson(json);
}

Expand Down Expand Up @@ -244,6 +245,21 @@
return this;
}

/// <summary>
/// Specifies the <see cref="JsonSerializerOptions"/> to use for all JSON serialization in this mock,
/// including body matching and response content generation.
/// </summary>
public RequestMockBuilder Using(JsonSerializerOptions options)
{
if (options is null)

Check notice

Code scanning / InspectCode

Join null check with assignment Note

Join null check with assignment
{
throw new ArgumentNullException(nameof(options));
}

jsonSerializerOptions = options;
return this;
}

/// <summary>
/// Responds with the specified HTTP status code.
/// </summary>
Expand Down Expand Up @@ -288,6 +304,8 @@
/// </summary>
public RequestMockResponseBuilder RespondsWithJsonContent(HttpStatusCode statusCode, object content)
{
var options = jsonSerializerOptions;

var mock = new RequestMock
{
Method = Method,
Expand All @@ -299,7 +317,7 @@
RequestCollection = requestCollection,
Responder = _ =>
{
var json = JsonSerializer.Serialize(content);
var json = JsonSerializer.Serialize(content, options);
return new HttpResponseMessage(statusCode)
{
Content = new StringContent(json, Encoding.UTF8, "application/json")
Expand Down Expand Up @@ -392,6 +410,8 @@
public RequestMockResponseBuilder RespondsWithODataResult(HttpStatusCode statusCode,
IEnumerable<object> value)
{
var options = jsonSerializerOptions;

var mock = new RequestMock
{
Method = Method,
Expand All @@ -408,7 +428,7 @@
["value"] = value.ToArray()
};

string json = JsonSerializer.Serialize(payload);
string json = JsonSerializer.Serialize(payload, options);
return new HttpResponseMessage(statusCode)
{
Content = new StringContent(json, Encoding.UTF8, "application/json")
Expand Down Expand Up @@ -439,6 +459,8 @@
public RequestMockResponseBuilder RespondsWithODataResult(HttpStatusCode statusCode, IEnumerable<object> value,
string odataContext)
{
var options = jsonSerializerOptions;

var mock = new RequestMock
{
Method = Method,
Expand All @@ -460,7 +482,7 @@
payload["@odata.context"] = odataContext;
}

string json = JsonSerializer.Serialize(payload);
string json = JsonSerializer.Serialize(payload, options);
return new HttpResponseMessage(statusCode)
{
Content = new StringContent(json, Encoding.UTF8, "application/json")
Expand Down
Loading