// Copyright © WireMock.Net using System.Text; using System.Text.Json.Nodes; using Moq; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using WireMock.Handlers; using WireMock.Settings; using WireMock.Transformers; using WireMock.Types; using WireMock.Util; namespace WireMock.Net.Tests.Transformers; public class JsonBodyTransformerTests { public static TheoryData Transformers { get { var settings = new WireMockServerSettings(); return [ new JsonBodyTransformerTestContext( () => new NewtonsoftJsonBodyTransformer(settings), JObject.Parse, body => ((JToken)body).ToString(Formatting.None)), new JsonBodyTransformerTestContext( () => new SystemTextJsonBodyTransformer(settings), json => JsonNode.Parse(json)!, body => ((JsonNode)body).ToJsonString()) ]; } } [Theory] [MemberData(nameof(Transformers))] public void TransformBodyAsJson_Replaces_String_Value_And_Preserves_Original(JsonBodyTransformerTestContext testContext) { // Arrange var transformer = testContext.CreateTransformer(); var originalJson = testContext.ParseJson("{\"value\":\"{{number}}\"}"); var bodyData = new BodyData { Encoding = Encoding.UTF8, DetectedBodyType = BodyType.Json, DetectedBodyTypeFromContentType = BodyType.Json, ProtoBufMessageType = "My.Message", BodyAsJson = originalJson }; var transformerContext = new FakeTransformerContext( text => text, text => text == "{{number}}" ? "123" : text); // Act var result = transformer.TransformBodyAsJson(transformerContext, ReplaceNodeOptions.EvaluateAndTryToConvert, new { }, bodyData); // Assert result.Encoding.Should().Be(Encoding.UTF8); result.DetectedBodyType.Should().Be(BodyType.Json); result.DetectedBodyTypeFromContentType.Should().Be(BodyType.Json); result.ProtoBufMessageType.Should().Be("My.Message"); result.BodyAsJson.Should().NotBeNull(); testContext.SerializeJson(result.BodyAsJson).Should().Be("{\"value\":123}"); testContext.SerializeJson(originalJson).Should().Be("{\"value\":\"{{number}}\"}"); } [Theory] [MemberData(nameof(Transformers))] public void TransformBodyAsJson_With_String_Body_Replaces_Single_Node_With_Object(JsonBodyTransformerTestContext testContext) { // Arrange var transformer = testContext.CreateTransformer(); var bodyData = new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = "{{json}}" }; var transformerContext = new FakeTransformerContext( text => text == "{{json}}" ? "{\"name\":\"test\"}" : text, text => text); // Act var result = transformer.TransformBodyAsJson(transformerContext, ReplaceNodeOptions.EvaluateAndTryToConvert, new { }, bodyData); // Assert result.BodyAsJson.Should().NotBeNull(); testContext.SerializeJson(result.BodyAsJson).Should().Be("{\"name\":\"test\"}"); } [Theory] [MemberData(nameof(Transformers))] public void TransformBodyAsJson_Replaces_String_Value_With_WireMockList_As_Array(JsonBodyTransformerTestContext testContext) { // Arrange var transformer = testContext.CreateTransformer(); var bodyData = new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = testContext.ParseJson("{\"values\":\"{{list}}\"}") }; var transformerContext = new FakeTransformerContext( text => text, text => text == "{{list}}" ? new WireMockList(["a", "b"]) : text); // Act var result = transformer.TransformBodyAsJson(transformerContext, ReplaceNodeOptions.EvaluateAndTryToConvert, new { }, bodyData); // Assert result.BodyAsJson.Should().NotBeNull(); testContext.SerializeJson(result.BodyAsJson).Should().Be("{\"values\":[\"a\",\"b\"]}"); } public sealed class JsonBodyTransformerTestContext { private readonly Func _createTransformer; private readonly Func _parseJson; private readonly Func _serializeJson; public JsonBodyTransformerTestContext( Func createTransformer, Func parseJson, Func serializeJson) { _createTransformer = createTransformer; _parseJson = parseJson; _serializeJson = serializeJson; } public IJsonBodyTransformer CreateTransformer() { return _createTransformer(); } public object ParseJson(string json) { return _parseJson(json); } public string SerializeJson(object body) { return _serializeJson(body); } } private sealed class FakeTransformerContext(Func parseAndRender, Func parseAndEvaluate) : ITransformerContext { public IFileSystemHandler FileSystemHandler { get; private set; } = Mock.Of(); public string ParseAndRender(string text, object model) { return parseAndRender(text); } public object ParseAndEvaluate(string text, object model) { return parseAndEvaluate(text); } } }