mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-15 08:03:31 +01:00
Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
9031541b91 | ||
|
|
bd030594d5 | ||
|
|
eed73ee8b3 | ||
|
|
8476e3c47f | ||
|
|
a7fbc051c9 | ||
|
|
6e45255c9e | ||
|
|
96e68ae2a0 |
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,3 +1,18 @@
|
||||
# 1.0.17.0 (05 June 2019)
|
||||
- [#278](https://github.com/WireMock-Net/WireMock.Net/pull/278) - Add support for HandleBars File (to read a file) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#276](https://github.com/WireMock-Net/WireMock.Net/issues/276) - No server response in Postman and Receive Failure in Fiddler [invalid]
|
||||
|
||||
# 1.0.16.0 (16 May 2019)
|
||||
- [#274](https://github.com/WireMock-Net/WireMock.Net/pull/274) - Sign Assembly [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#160](https://github.com/WireMock-Net/WireMock.Net/issues/160) - Feature: Sign 'WireMock.Net' [feature]
|
||||
- [#267](https://github.com/WireMock-Net/WireMock.Net/issues/267) - Assembly does not have strong name
|
||||
|
||||
# 1.0.15.0 (04 May 2019)
|
||||
- [#271](https://github.com/WireMock-Net/WireMock.Net/pull/271) - Support Dynamic response files using Handlebars templating [bug, feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#272](https://github.com/WireMock-Net/WireMock.Net/pull/272) - Add unit test for JsonPath and BodyAsFile mapping contributed by [denstorti](https://github.com/denstorti)
|
||||
- [#273](https://github.com/WireMock-Net/WireMock.Net/pull/273) - Dynamic response handlebars templating (2) [bug, feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#270](https://github.com/WireMock-Net/WireMock.Net/issues/270) - Dynamic response files using Handlebars templating [bug, question]
|
||||
|
||||
# 1.0.14.0 (20 April 2019)
|
||||
- [#269](https://github.com/WireMock-Net/WireMock.Net/pull/269) - Add JmesPath matcher [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#268](https://github.com/WireMock-Net/WireMock.Net/issues/268) - Swagger UI for admin api [question]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.0.14</VersionPrefix>
|
||||
<VersionPrefix>1.0.17</VersionPrefix>
|
||||
</PropertyGroup>
|
||||
|
||||
<Choose>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --version 1.0.14.0
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --version 1.0.17.0
|
||||
@@ -8,7 +8,7 @@ A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) w
|
||||
* Record/playback of stubs (proxying)
|
||||
* Per-request conditional proxying
|
||||
* Stateful behaviour simulation
|
||||
* Response transformation
|
||||
* Response templating / transformation using Handlebars and extensions
|
||||
|
||||
## Info
|
||||
| | |
|
||||
|
||||
@@ -50,6 +50,12 @@ namespace WireMock.Net.ConsoleApplication
|
||||
return File.ReadAllBytes(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsFile"/>
|
||||
public string ReadResponseBodyAsString(string path)
|
||||
{
|
||||
return File.ReadAllText(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
|
||||
public bool FileExists(string path)
|
||||
{
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.Tests")]
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
|
||||
|
||||
// Needed for Moq in the UnitTest project
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
@@ -25,6 +25,10 @@
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<CodeAnalysisRuleSet>WireMock.Net.StandAlone.ruleset</CodeAnalysisRuleSet>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
|
||||
@@ -49,12 +49,19 @@ namespace WireMock.Handlers
|
||||
void WriteMappingFile([NotNull] string path, [NotNull] string text);
|
||||
|
||||
/// <summary>
|
||||
/// Read a response body file as text.
|
||||
/// Read a response body file as byte[].
|
||||
/// </summary>
|
||||
/// <param name="path">The path or filename from the file to read.</param>
|
||||
/// <returns>The file content as bytes.</returns>
|
||||
byte[] ReadResponseBodyAsFile([NotNull] string path);
|
||||
|
||||
/// <summary>
|
||||
/// Read a response body file as text.
|
||||
/// </summary>
|
||||
/// <param name="path">The path or filename from the file to read.</param>
|
||||
/// <returns>The file content as text.</returns>
|
||||
string ReadResponseBodyAsString([NotNull] string path);
|
||||
|
||||
/// <summary>
|
||||
/// Delete a file.
|
||||
/// </summary>
|
||||
|
||||
@@ -68,6 +68,16 @@ namespace WireMock.Handlers
|
||||
return File.ReadAllBytes(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsString"/>
|
||||
public string ReadResponseBodyAsString(string path)
|
||||
{
|
||||
Check.NotNullOrEmpty(path, nameof(path));
|
||||
|
||||
// In case the path is a filename, the path will be adjusted to the MappingFolder.
|
||||
// Else the path will just be as-is.
|
||||
return File.ReadAllText(Path.GetFileName(path) == path ? Path.Combine(GetMappingFolder(), path) : path);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
|
||||
public bool FileExists(string filename)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.StandAlone")]
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.Tests")]
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.StandAlone, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
|
||||
[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
|
||||
|
||||
// Needed for Moq in the UnitTest project
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
|
||||
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
|
||||
@@ -21,7 +21,8 @@ namespace WireMock.ResponseBuilders
|
||||
/// </summary>
|
||||
public class Response : IResponseBuilder
|
||||
{
|
||||
private readonly IFileSystemHandler _fileSystemHandler = new LocalFileSystemHandler();
|
||||
private readonly IFileSystemHandler _fileSystemHandler;
|
||||
private readonly ResponseMessageTransformer _responseMessageTransformer;
|
||||
private HttpClient _httpClientForProxy;
|
||||
|
||||
/// <summary>
|
||||
@@ -93,6 +94,9 @@ namespace WireMock.ResponseBuilders
|
||||
private Response(ResponseMessage responseMessage)
|
||||
{
|
||||
ResponseMessage = responseMessage;
|
||||
|
||||
_fileSystemHandler = new LocalFileSystemHandler();
|
||||
_responseMessageTransformer = new ResponseMessageTransformer(_fileSystemHandler);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -224,7 +228,7 @@ namespace WireMock.ResponseBuilders
|
||||
BodyAsFileIsCached = cache
|
||||
};
|
||||
|
||||
if (cache)
|
||||
if (cache && !UseTransformer)
|
||||
{
|
||||
ResponseMessage.BodyData.DetectedBodyType = BodyType.Bytes;
|
||||
ResponseMessage.BodyData.BodyAsBytes = _fileSystemHandler.ReadResponseBodyAsFile(filename);
|
||||
@@ -417,7 +421,7 @@ namespace WireMock.ResponseBuilders
|
||||
|
||||
if (UseTransformer)
|
||||
{
|
||||
return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage);
|
||||
return _responseMessageTransformer.Transform(requestMessage, ResponseMessage);
|
||||
}
|
||||
|
||||
// Just return normal defined ResponseMessage
|
||||
|
||||
@@ -722,6 +722,11 @@ namespace WireMock.Server
|
||||
responseBuilder = responseBuilder.WithDelay(responseModel.Delay.Value);
|
||||
}
|
||||
|
||||
if (responseModel.UseTransformer)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithTransformer();
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(responseModel.ProxyUrl))
|
||||
{
|
||||
if (string.IsNullOrEmpty(responseModel.X509Certificate2ThumbprintOrSubjectName))
|
||||
@@ -778,11 +783,6 @@ namespace WireMock.Server
|
||||
responseBuilder = responseBuilder.WithBodyFromFile(responseModel.BodyAsFile);
|
||||
}
|
||||
|
||||
if (responseModel.UseTransformer)
|
||||
{
|
||||
responseBuilder = responseBuilder.WithTransformer();
|
||||
}
|
||||
|
||||
return responseBuilder;
|
||||
}
|
||||
|
||||
|
||||
41
src/WireMock.Net/Transformers/HandleBarsFile.cs
Normal file
41
src/WireMock.Net/Transformers/HandleBarsFile.cs
Normal file
@@ -0,0 +1,41 @@
|
||||
using HandlebarsDotNet;
|
||||
using System;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
internal static class HandleBarsFile
|
||||
{
|
||||
public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler)
|
||||
{
|
||||
handlebarsContext.RegisterHelper("File", (writer, context, arguments) =>
|
||||
{
|
||||
string value = ParseArgumentAndReadFileFragment(handlebarsContext, context, fileSystemHandler, arguments);
|
||||
writer.Write(value);
|
||||
});
|
||||
|
||||
handlebarsContext.RegisterHelper("File", (writer, options, context, arguments) =>
|
||||
{
|
||||
string value = ParseArgumentAndReadFileFragment(handlebarsContext, context, fileSystemHandler, arguments);
|
||||
options.Template(writer, value);
|
||||
});
|
||||
}
|
||||
|
||||
private static string ParseArgumentAndReadFileFragment(IHandlebars handlebarsContext, dynamic context, IFileSystemHandler fileSystemHandler, object[] arguments)
|
||||
{
|
||||
Check.Condition(arguments, args => args.Length == 1, nameof(arguments));
|
||||
Check.NotNull(arguments[0], "arguments[0]");
|
||||
|
||||
switch (arguments[0])
|
||||
{
|
||||
case string path:
|
||||
var templateFunc = handlebarsContext.Compile(path);
|
||||
string transformed = templateFunc(context);
|
||||
return fileSystemHandler.ReadResponseBodyAsString(transformed);
|
||||
}
|
||||
|
||||
throw new NotSupportedException($"The value '{arguments[0]}' with type '{arguments[0]?.GetType()}' cannot be used in Handlebars File.");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,11 @@
|
||||
using HandlebarsDotNet;
|
||||
using WireMock.Handlers;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
internal static class HandlebarsHelpers
|
||||
{
|
||||
public static void Register(IHandlebars handlebarsContext)
|
||||
public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler)
|
||||
{
|
||||
HandleBarsRegex.Register(handlebarsContext);
|
||||
|
||||
@@ -15,6 +16,8 @@ namespace WireMock.Transformers
|
||||
HandleBarsRandom.Register(handlebarsContext);
|
||||
|
||||
HandleBarsXeger.Register(handlebarsContext);
|
||||
|
||||
HandleBarsFile.Register(handlebarsContext, fileSystemHandler);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,17 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using HandlebarsDotNet;
|
||||
using HandlebarsDotNet;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Util;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Transformers
|
||||
{
|
||||
internal static class ResponseMessageTransformer
|
||||
internal class ResponseMessageTransformer
|
||||
{
|
||||
private static readonly HandlebarsConfiguration HandlebarsConfiguration = new HandlebarsConfiguration
|
||||
{
|
||||
@@ -17,30 +20,33 @@ namespace WireMock.Transformers
|
||||
|
||||
private static readonly IHandlebars HandlebarsContext = Handlebars.Create(HandlebarsConfiguration);
|
||||
|
||||
static ResponseMessageTransformer()
|
||||
public ResponseMessageTransformer([NotNull] IFileSystemHandler fileSystemHandler)
|
||||
{
|
||||
HandlebarsHelpers.Register(HandlebarsContext);
|
||||
Check.NotNull(fileSystemHandler, nameof(fileSystemHandler));
|
||||
|
||||
HandlebarsHelpers.Register(HandlebarsContext, fileSystemHandler);
|
||||
}
|
||||
|
||||
public static ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original)
|
||||
public ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original)
|
||||
{
|
||||
bool bodyIsJson = original.BodyData.DetectedBodyType == BodyType.Json;
|
||||
var responseMessage = new ResponseMessage { StatusCode = original.StatusCode };
|
||||
|
||||
if (!bodyIsJson)
|
||||
{
|
||||
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
|
||||
}
|
||||
|
||||
var template = new { request = requestMessage };
|
||||
|
||||
if (!bodyIsJson)
|
||||
switch (original.BodyData.DetectedBodyType)
|
||||
{
|
||||
TransformBodyAsString(template, original, responseMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
TransformBodyAsJson(template, original, responseMessage);
|
||||
case BodyType.Json:
|
||||
TransformBodyAsJson(template, original, responseMessage);
|
||||
break;
|
||||
|
||||
case BodyType.File:
|
||||
TransformBodyAsFile(template, original, responseMessage);
|
||||
break;
|
||||
|
||||
case BodyType.String:
|
||||
responseMessage.BodyOriginal = original.BodyData.BodyAsString;
|
||||
TransformBodyAsString(template, original, responseMessage);
|
||||
break;
|
||||
}
|
||||
|
||||
// Headers
|
||||
@@ -89,14 +95,14 @@ namespace WireMock.Transformers
|
||||
};
|
||||
}
|
||||
|
||||
private static void WalkNode(JToken node, object template)
|
||||
private static void WalkNode(JToken node, object context)
|
||||
{
|
||||
if (node.Type == JTokenType.Object)
|
||||
{
|
||||
// In case of Object, loop all children. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||
foreach (JProperty child in node.Children<JProperty>().ToArray())
|
||||
{
|
||||
WalkNode(child.Value, template);
|
||||
WalkNode(child.Value, context);
|
||||
}
|
||||
}
|
||||
else if (node.Type == JTokenType.Array)
|
||||
@@ -104,7 +110,7 @@ namespace WireMock.Transformers
|
||||
// In case of Array, loop all items. Do a ToArray() to avoid `Collection was modified` exceptions.
|
||||
foreach (JToken child in node.Children().ToArray())
|
||||
{
|
||||
WalkNode(child, template);
|
||||
WalkNode(child, context);
|
||||
}
|
||||
}
|
||||
else if (node.Type == JTokenType.String)
|
||||
@@ -117,7 +123,7 @@ namespace WireMock.Transformers
|
||||
}
|
||||
|
||||
var templateForStringValue = HandlebarsContext.Compile(stringValue);
|
||||
string transformedString = templateForStringValue(template);
|
||||
string transformedString = templateForStringValue(context);
|
||||
if (!string.Equals(stringValue, transformedString))
|
||||
{
|
||||
ReplaceNodeValue(node, transformedString);
|
||||
@@ -150,13 +156,25 @@ namespace WireMock.Transformers
|
||||
|
||||
private static void TransformBodyAsString(object template, ResponseMessage original, ResponseMessage responseMessage)
|
||||
{
|
||||
var templateBody = HandlebarsContext.Compile(original.BodyData.BodyAsString);
|
||||
var templateBodyAsString = HandlebarsContext.Compile(original.BodyData.BodyAsString);
|
||||
|
||||
responseMessage.BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = original.BodyData.DetectedBodyType,
|
||||
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
|
||||
BodyAsString = templateBody(template)
|
||||
BodyAsString = templateBodyAsString(template)
|
||||
};
|
||||
}
|
||||
|
||||
private static void TransformBodyAsFile(object template, ResponseMessage original, ResponseMessage responseMessage)
|
||||
{
|
||||
var templateBodyAsFile = HandlebarsContext.Compile(original.BodyData.BodyAsFile);
|
||||
|
||||
responseMessage.BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = original.BodyData.DetectedBodyType,
|
||||
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
|
||||
BodyAsFile = templateBodyAsFile(template)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,10 @@
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<CodeAnalysisRuleSet>WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
@@ -58,7 +62,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.7" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.8" />
|
||||
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
BIN
src/WireMock.Net/WireMock.Net.snk
Normal file
BIN
src/WireMock.Net/WireMock.Net.snk
Normal file
Binary file not shown.
@@ -0,0 +1,102 @@
|
||||
using Moq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NFluent;
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Transformers;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithHandlebarsFileTests
|
||||
{
|
||||
private readonly Mock<IFileSystemHandler> _filesystemHandlerMock;
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
public ResponseWithHandlebarsFileTests()
|
||||
{
|
||||
_filesystemHandlerMock = new Mock<IFileSystemHandler>(MockBehavior.Strict);
|
||||
_filesystemHandlerMock.Setup(fs => fs.ReadResponseBodyAsString(It.IsAny<string>())).Returns("abc");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponseAsync_Handlebars_File()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBodyAsJson(new
|
||||
{
|
||||
Data = "{{File \"x.json\"}}"
|
||||
})
|
||||
.WithTransformer();
|
||||
|
||||
response.SetPrivateFieldValue("_fileSystemHandler", _filesystemHandlerMock.Object);
|
||||
response.SetPrivateFieldValue("_responseMessageTransformer", new ResponseMessageTransformer(_filesystemHandlerMock.Object));
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
Check.That(j["Data"].Value<string>()).Equals("abc");
|
||||
|
||||
// Verify
|
||||
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString("x.json"), Times.Once);
|
||||
_filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponseAsync_Handlebars_File_Replace()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234?id=x"), "GET", ClientIp);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBodyAsJson(new
|
||||
{
|
||||
Data = "{{File \"{{request.query.id}}.json\"}}"
|
||||
})
|
||||
.WithTransformer();
|
||||
|
||||
response.SetPrivateFieldValue("_fileSystemHandler", _filesystemHandlerMock.Object);
|
||||
response.SetPrivateFieldValue("_responseMessageTransformer", new ResponseMessageTransformer(_filesystemHandlerMock.Object));
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// Assert
|
||||
JObject j = JObject.FromObject(responseMessage.BodyData.BodyAsJson);
|
||||
Check.That(j["Data"].Value<string>()).Equals("abc");
|
||||
|
||||
// Verify
|
||||
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString("x.json"), Times.Once);
|
||||
_filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void Response_ProvideResponseAsync_Handlebars_File_WithMissingArgument_ThrowsArgumentOutOfRangeException()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "GET", ClientIp);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithBodyAsJson(new
|
||||
{
|
||||
Data = "{{File}}"
|
||||
})
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request)).Throws<ArgumentOutOfRangeException>();
|
||||
|
||||
// Verify
|
||||
_filesystemHandlerMock.Verify(fs => fs.ReadResponseBodyAsString(It.IsAny<string>()), Times.Never);
|
||||
_filesystemHandlerMock.VerifyNoOtherCalls();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -214,5 +214,49 @@ namespace WireMock.Net.Tests.ResponseBuilders
|
||||
// Assert
|
||||
Check.That(JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson)).Equals("[\"first\",\"/foo_array\",\"test 1\",\"test 2\",\"last\"]");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_WithBodyAsFile()
|
||||
{
|
||||
// Assign
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo?MyUniqueNumber=1"), "GET", ClientIp);
|
||||
|
||||
var response = Response.Create()
|
||||
.WithTransformer()
|
||||
.WithBodyFromFile(@"c:\\{{request.query.MyUniqueNumber}}\test.xml"); // why use a \\ here ?
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsFile).Equals(@"c:\1\test.xml");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_ProvideResponse_Handlebars_WithBodyAsFile_JsonPath()
|
||||
{
|
||||
// Assign
|
||||
string jsonString = "{ \"MyUniqueNumber\": \"1\" }";
|
||||
var bodyData = new BodyData
|
||||
{
|
||||
BodyAsString = jsonString,
|
||||
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
|
||||
DetectedBodyType = BodyType.Json,
|
||||
DetectedBodyTypeFromContentType = BodyType.Json,
|
||||
Encoding = Encoding.UTF8
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "POST", ClientIp, bodyData);
|
||||
|
||||
string jsonPath = "\"$.MyUniqueNumber\"";
|
||||
var response = Response.Create()
|
||||
.WithTransformer()
|
||||
.WithBodyFromFile(@"c:\\{{JsonPath.SelectToken request.body " + jsonPath + "}}\\test.json"); // why use a \\ here ?
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(request);
|
||||
|
||||
// Assert
|
||||
Check.That(responseMessage.BodyData.BodyAsFile).Equals(@"c:\1\test.json");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Reflection;
|
||||
using System;
|
||||
using System.Reflection;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
@@ -10,5 +11,53 @@ namespace WireMock.Net.Tests
|
||||
|
||||
return (T)field.GetValue(obj);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set a _private_ Field Value on a given Object
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the Property</typeparam>
|
||||
/// <param name="obj">Object from where the Property Value is returned</param>
|
||||
/// <param name="propertyName">Property name as string.</param>
|
||||
/// <param name="value">the value to set</param>
|
||||
public static void SetPrivateFieldValue<T>(this object obj, string propertyName, T value)
|
||||
{
|
||||
if (obj == null)
|
||||
{
|
||||
throw new ArgumentNullException(nameof(obj));
|
||||
}
|
||||
|
||||
Type t = obj.GetType();
|
||||
FieldInfo fi = null;
|
||||
while (fi == null && t != null)
|
||||
{
|
||||
fi = t.GetField(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||
t = t.BaseType;
|
||||
}
|
||||
|
||||
if (fi == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(propertyName), $"Field {propertyName} was not found in Type {obj.GetType().FullName}");
|
||||
}
|
||||
|
||||
fi.SetValue(obj, value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Sets a _private_ Property Value from a given Object.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">Type of the Property</typeparam>
|
||||
/// <param name="obj">Object from where the Property Value is set</param>
|
||||
/// <param name="propertyName">Property name as string.</param>
|
||||
/// <param name="value">Value to set.</param>
|
||||
public static void SetPrivatePropertyValue<T>(this object obj, string propertyName, T value)
|
||||
{
|
||||
Type t = obj.GetType();
|
||||
if (t.GetProperty(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance) == null)
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(propertyName), $"Property {propertyName} was not found in Type {obj.GetType().FullName}");
|
||||
}
|
||||
|
||||
t.InvokeMember(propertyName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.SetProperty | BindingFlags.Instance, null, obj, new object[] { value });
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,14 @@
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<SonarQubeTestProject>True</SonarQubeTestProject>
|
||||
<SonarQubeExclude>True</SonarQubeExclude>
|
||||
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
@@ -28,6 +36,8 @@
|
||||
</PackageReference>
|
||||
<PackageReference Include="System.Threading" Version="4.3.0" />
|
||||
|
||||
<PackageReference Include="RestEase" Version="1.4.7" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.8" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.9.0" />
|
||||
<PackageReference Include="MimeKitLite" Version="2.0.7" />
|
||||
<PackageReference Include="Moq" Version="4.10.1" />
|
||||
@@ -42,6 +52,7 @@
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<!--<PackageReference Include="StrongNamer" Version="0.0.8" />-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net452'">
|
||||
|
||||
Reference in New Issue
Block a user