Add IFileSystemHandler to support Azure for StaticMapping location (#180)

* wip

* CustomStaticMappingFileHandler

* Add unit-tests

* Tests

* IFileSystemHandler

* version
This commit is contained in:
Stef Heyenrath
2018-08-14 18:54:53 +02:00
committed by GitHub
parent c92e733ef9
commit 4b91c05fe7
21 changed files with 505 additions and 59 deletions

View File

@@ -54,6 +54,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Service", "exa
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.HeadersTest", "examples\WireMock.Net.Console.HeadersTest\WireMock.Net.Console.HeadersTest.csproj", "{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}" Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.HeadersTest", "examples\WireMock.Net.Console.HeadersTest\WireMock.Net.Console.HeadersTest.csproj", "{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}"
EndProject EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NETCoreApp2", "examples\WireMock.Net.Console.NETCoreApp2\WireMock.Net.Console.NETCoreApp2.csproj", "{83645809-9E01-4E81-8733-BA9497554ABF}"
EndProject
Global Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU Debug|Any CPU = Debug|Any CPU
@@ -120,6 +122,10 @@ Global
{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Debug|Any CPU.Build.0 = Debug|Any CPU {B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Release|Any CPU.ActiveCfg = Release|Any CPU {B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Release|Any CPU.Build.0 = Release|Any CPU {B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C}.Release|Any CPU.Build.0 = Release|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Debug|Any CPU.Build.0 = Debug|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Release|Any CPU.ActiveCfg = Release|Any CPU
{83645809-9E01-4E81-8733-BA9497554ABF}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection EndGlobalSection
GlobalSection(SolutionProperties) = preSolution GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE HideSolutionNode = FALSE
@@ -140,6 +146,7 @@ Global
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A} {3C279524-DB73-4DE3-BEF1-F2B2958C9F65} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{7F0B2446-0363-4720-AF46-F47F83B557DC} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A} {7F0B2446-0363-4720-AF46-F47F83B557DC} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A} {B70278E7-A2C6-4A3B-BBA9-1C873CA6F03C} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{83645809-9E01-4E81-8733-BA9497554ABF} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
EndGlobalSection EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BF428BCC-C837-433B-87D2-15C7014B73E9} SolutionGuid = {BF428BCC-C837-433B-87D2-15C7014B73E9}

View File

@@ -7,6 +7,7 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Include="..\WireMock.Net.ConsoleApplication\CustomFileSystemFileHandler.cs" Link="CustomFileSystemFileHandler.cs" />
<Compile Include="..\WireMock.Net.ConsoleApplication\MainApp.cs" Link="MainApp.cs" /> <Compile Include="..\WireMock.Net.ConsoleApplication\MainApp.cs" Link="MainApp.cs" />
</ItemGroup> </ItemGroup>

View File

@@ -0,0 +1,48 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>netcoreapp2.1</TargetFramework>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
<StartupObject>WireMock.Net.Console.NETCoreApp.Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\WireMock.Net.ConsoleApplication\CustomFileSystemFileHandler.cs" Link="CustomFileSystemFileHandler.cs" />
<Compile Include="..\WireMock.Net.ConsoleApplication\MainApp.cs" Link="MainApp.cs" />
<Compile Include="..\WireMock.Net.Console.NETCoreApp\Program.cs" Link="Program.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="__admin\mappings\*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
<ItemGroup>
<None Include="..\WireMock.Net.Console.NETCoreApp\log4net.config" Link="log4net.config" />
<None Include="..\WireMock.Net.Console.NETCoreApp\nlog.config" Link="nlog.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
<PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="10.0.3" />
</ItemGroup>
<ItemGroup>
<None Update="log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="nlog.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="__admin\mappings\791a3f31-6946-4ce7-8e6f-0237c7443275.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Update="__admin\mappings\791a3f31-6946-4ce7-8e6f-0237c7443275.json">
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,22 @@
{
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/static/mapping"
}
]
},
"Methods": [
"get"
]
},
"Response": {
"BodyAsJson": { "body": "static mapping" },
"Headers": {
"Content-Type": "application/json",
"Test-X": [ "test 1", "test 2" ]
}
}
}

View File

@@ -0,0 +1,29 @@
{
"Guid": "791a3f31-6946-4ce7-8e6f-0237c7443275",
"Title": "",
"Priority": 0,
"Request": {
"Path": "/proxy-google-test-post",
"Methods": [
"post"
],
"Body": {}
},
"Response": {
"StatusCode": 404,
"Body": "<!DOCTYPE html>\n<html lang=en>\n <meta charset=utf-8>\n <meta name=viewport content=\"initial-scale=1, minimum-scale=1, width=device-width\">\n <title>Error 404 (Not Found)!!1</title>\n <style>\n *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\n </style>\n <a href=//www.google.com/><span id=logo aria-label=Google></span></a>\n <p><b>404.</b> <ins>Thats an error.</ins>\n <p>The requested URL <code>/proxy-google-test-post</code> was not found on this server. <ins>Thats all we know.</ins>\n",
"BodyAsBytes": "PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CiAgPG1ldGEgY2hhcnNldD11dGYtOD4KICA8bWV0YSBuYW1lPXZpZXdwb3J0IGNvbnRlbnQ9ImluaXRpYWwtc2NhbGU9MSwgbWluaW11bS1zY2FsZT0xLCB3aWR0aD1kZXZpY2Utd2lkdGgiPgogIDx0aXRsZT5FcnJvciA0MDQgKE5vdCBGb3VuZCkhITE8L3RpdGxlPgogIDxzdHlsZT4KICAgICp7bWFyZ2luOjA7cGFkZGluZzowfWh0bWwsY29kZXtmb250OjE1cHgvMjJweCBhcmlhbCxzYW5zLXNlcmlmfWh0bWx7YmFja2dyb3VuZDojZmZmO2NvbG9yOiMyMjI7cGFkZGluZzoxNXB4fWJvZHl7bWFyZ2luOjclIGF1dG8gMDttYXgtd2lkdGg6MzkwcHg7bWluLWhlaWdodDoxODBweDtwYWRkaW5nOjMwcHggMCAxNXB4fSogPiBib2R5e2JhY2tncm91bmQ6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2Vycm9ycy9yb2JvdC5wbmcpIDEwMCUgNXB4IG5vLXJlcGVhdDtwYWRkaW5nLXJpZ2h0OjIwNXB4fXB7bWFyZ2luOjExcHggMCAyMnB4O292ZXJmbG93OmhpZGRlbn1pbnN7Y29sb3I6Izc3Nzt0ZXh0LWRlY29yYXRpb246bm9uZX1hIGltZ3tib3JkZXI6MH1AbWVkaWEgc2NyZWVuIGFuZCAobWF4LXdpZHRoOjc3MnB4KXtib2R5e2JhY2tncm91bmQ6bm9uZTttYXJnaW4tdG9wOjA7bWF4LXdpZHRoOm5vbmU7cGFkZGluZy1yaWdodDowfX0jbG9nb3tiYWNrZ3JvdW5kOnVybCgvL3d3dy5nb29nbGUuY29tL2ltYWdlcy9icmFuZGluZy9nb29nbGVsb2dvLzF4L2dvb2dsZWxvZ29fY29sb3JfMTUweDU0ZHAucG5nKSBuby1yZXBlYXQ7bWFyZ2luLWxlZnQ6LTVweH1AbWVkaWEgb25seSBzY3JlZW4gYW5kIChtaW4tcmVzb2x1dGlvbjoxOTJkcGkpeyNsb2dve2JhY2tncm91bmQ6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2JyYW5kaW5nL2dvb2dsZWxvZ28vMngvZ29vZ2xlbG9nb19jb2xvcl8xNTB4NTRkcC5wbmcpIG5vLXJlcGVhdCAwJSAwJS8xMDAlIDEwMCU7LW1vei1ib3JkZXItaW1hZ2U6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2JyYW5kaW5nL2dvb2dsZWxvZ28vMngvZ29vZ2xlbG9nb19jb2xvcl8xNTB4NTRkcC5wbmcpIDB9fUBtZWRpYSBvbmx5IHNjcmVlbiBhbmQgKC13ZWJraXQtbWluLWRldmljZS1waXhlbC1yYXRpbzoyKXsjbG9nb3tiYWNrZ3JvdW5kOnVybCgvL3d3dy5nb29nbGUuY29tL2ltYWdlcy9icmFuZGluZy9nb29nbGVsb2dvLzJ4L2dvb2dsZWxvZ29fY29sb3JfMTUweDU0ZHAucG5nKSBuby1yZXBlYXQ7LXdlYmtpdC1iYWNrZ3JvdW5kLXNpemU6MTAwJSAxMDAlfX0jbG9nb3tkaXNwbGF5OmlubGluZS1ibG9jaztoZWlnaHQ6NTRweDt3aWR0aDoxNTBweH0KICA8L3N0eWxlPgogIDxhIGhyZWY9Ly93d3cuZ29vZ2xlLmNvbS8+PHNwYW4gaWQ9bG9nbyBhcmlhLWxhYmVsPUdvb2dsZT48L3NwYW4+PC9hPgogIDxwPjxiPjQwNC48L2I+IDxpbnM+VGhhdOKAmXMgYW4gZXJyb3IuPC9pbnM+CiAgPHA+VGhlIHJlcXVlc3RlZCBVUkwgPGNvZGU+L3Byb3h5LWdvb2dsZS10ZXN0LXBvc3Q8L2NvZGU+IHdhcyBub3QgZm91bmQgb24gdGhpcyBzZXJ2ZXIuICA8aW5zPlRoYXTigJlzIGFsbCB3ZSBrbm93LjwvaW5zPgo=",
"BodyEncoding": {
"CodePage": 65001,
"EncodingName": "Unicode (UTF-8)",
"WebName": "utf-8"
},
"UseTransformer": false,
"Headers": {
"Date": "Wed, 27 Oct 2017 18:57:40 GMT",
"Alt-Svc": "quic=\":443\"; ma=2592000; v=\"39,38,37,35\"",
"Referrer-Policy": "no-referrer",
"Connection": "close"
}
}
}

View File

@@ -0,0 +1,19 @@
{
"Guid": "873d495f-940e-4b86-a1f4-4f0fc7be8b8b",
"Priority": 4,
"Request": {
"Path": {},
"Methods": [
"get"
]
},
"Response": {
"StatusCode": 200,
"BodyDestination": "SameAsSource",
"Body": "NO PATH OR URL",
"UseTransformer": false,
"Headers": {
"Content-Type": "application/json"
}
}
}

View File

@@ -0,0 +1,47 @@
using System.Collections.Generic;
using System.IO;
using WireMock.Handlers;
namespace WireMock.Net.ConsoleApplication
{
internal class CustomFileSystemFileHandler : IFileSystemHandler
{
private static readonly string AdminMappingsFolder = Path.Combine("__admin", "mappings");
/// <inheritdoc cref="IFileSystemHandler.FolderExists"/>
public bool FolderExists(string path)
{
return Directory.Exists(path);
}
/// <inheritdoc cref="IFileSystemHandler.CreateFolder"/>
public void CreateFolder(string path)
{
Directory.CreateDirectory(path);
}
/// <inheritdoc cref="IFileSystemHandler.EnumerateFiles"/>
public IEnumerable<string> EnumerateFiles(string path)
{
return Directory.EnumerateFiles(path);
}
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
public string GetMappingFolder()
{
return Path.Combine(@"c:\temp-wiremock", AdminMappingsFolder);
}
/// <inheritdoc cref="IFileSystemHandler.ReadMappingFile"/>
public string ReadMappingFile(string path)
{
return File.ReadAllText(path);
}
/// <inheritdoc cref="IFileSystemHandler.WriteMappingFile"/>
public void WriteMappingFile(string path, string text)
{
File.WriteAllText(path, text);
}
}
}

View File

@@ -30,7 +30,9 @@ namespace WireMock.Net.ConsoleApplication
//}, //},
PreWireMockMiddlewareInit = app => { System.Console.WriteLine($"PreWireMockMiddlewareInit : {app.GetType()}"); }, PreWireMockMiddlewareInit = app => { System.Console.WriteLine($"PreWireMockMiddlewareInit : {app.GetType()}"); },
PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); }, PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); },
Logger = new WireMockConsoleLogger() Logger = new WireMockConsoleLogger(),
FileSystemHandler = new CustomFileSystemFileHandler()
}); });
System.Console.WriteLine("FluentMockServer listening at {0}", string.Join(",", server.Urls)); System.Console.WriteLine("FluentMockServer listening at {0}", string.Join(",", server.Urls));

View File

@@ -54,6 +54,7 @@
<Reference Include="System.XML" /> <Reference Include="System.XML" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="CustomFileSystemFileHandler.cs" />
<Compile Include="MainApp.cs" /> <Compile Include="MainApp.cs" />
<Compile Include="Program.cs" /> <Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" /> <Compile Include="Properties\AssemblyInfo.cs" />

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Description>Lightweight StandAlone Http Mocking Server for .Net.</Description> <Description>Lightweight StandAlone Http Mocking Server for .Net.</Description>
<AssemblyTitle>WireMock.Net.StandAlone</AssemblyTitle> <AssemblyTitle>WireMock.Net.StandAlone</AssemblyTitle>
<Version>1.0.4.9</Version> <Version>1.0.4.10</Version>
<Authors>Stef Heyenrath</Authors> <Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks> <TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>

View File

@@ -0,0 +1,49 @@
using System.Collections.Generic;
namespace WireMock.Handlers
{
/// <summary>
/// Handler to interact with the file system to handle folders and read and write static mapping files.
/// </summary>
public interface IFileSystemHandler
{
/// <summary>
/// Gets the folder where the static mappings are located. For local file system, this would be `{CurrentFolder}/__admin/mappings`.
/// </summary>
/// <returns>The foldername.</returns>
string GetMappingFolder();
/// <summary>
/// Determines whether the given path refers to an existing directory on disk.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>true if path refers to an existing directory; false if the directory does not exist or an error occurs when trying to determine if the specified directory exists.</returns>
bool FolderExists(string path);
/// <summary>
/// Creates all directories and subdirectories in the specified path unless they already exist.
/// </summary>
/// <param name="path">The path.</param>
void CreateFolder(string path);
/// <summary>
/// Returns an enumerable collection of file names in a specified path.
/// </summary>
/// <param name="path">The path.</param>
/// <returns>An enumerable collection of the full names (including paths) for the files in the directory specified by path.</returns>
IEnumerable<string> EnumerateFiles(string path);
/// <summary>
/// Read a static mapping file as text.
/// </summary>
/// <param name="path">The path (folder + filename with .json extension).</param>
string ReadMappingFile(string path);
/// <summary>
/// Write the static mapping.
/// </summary>
/// <param name="path">The path (folder + filename with .json extension).</param>
/// <param name="text">The text.</param>
void WriteMappingFile(string path, string text);
}
}

View File

@@ -0,0 +1,49 @@
using System.Collections.Generic;
using System.IO;
namespace WireMock.Handlers
{
/// <summary>
/// Default implementation for a handler to interact with the local file system to read and write static mapping files.
/// </summary>
public class LocalFileSystemHandler : IFileSystemHandler
{
private static readonly string AdminMappingsFolder = Path.Combine("__admin", "mappings");
/// <inheritdoc cref="IFileSystemHandler.FolderExists"/>
public bool FolderExists(string path)
{
return Directory.Exists(path);
}
/// <inheritdoc cref="IFileSystemHandler.CreateFolder"/>
public void CreateFolder(string path)
{
Directory.CreateDirectory(path);
}
/// <inheritdoc cref="IFileSystemHandler.EnumerateFiles"/>
public IEnumerable<string> EnumerateFiles(string path)
{
return Directory.EnumerateFiles(path);
}
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
public string GetMappingFolder()
{
return Path.Combine(Directory.GetCurrentDirectory(), AdminMappingsFolder);
}
/// <inheritdoc cref="IFileSystemHandler.ReadMappingFile"/>
public string ReadMappingFile(string path)
{
return File.ReadAllText(path);
}
/// <inheritdoc cref="IFileSystemHandler.WriteMappingFile"/>
public void WriteMappingFile(string path, string text)
{
File.WriteAllText(path, text);
}
}
}

View File

@@ -30,12 +30,13 @@ namespace WireMock.Server
/// </summary> /// </summary>
public partial class FluentMockServer public partial class FluentMockServer
{ {
private static readonly string AdminMappingsFolder = Path.Combine("__admin", "mappings");
private const string ContentTypeJson = "application/json"; private const string ContentTypeJson = "application/json";
private const string AdminMappings = "/__admin/mappings"; private const string AdminMappings = "/__admin/mappings";
private const string AdminRequests = "/__admin/requests"; private const string AdminRequests = "/__admin/requests";
private const string AdminSettings = "/__admin/settings"; private const string AdminSettings = "/__admin/settings";
private const string AdminScenarios = "/__admin/scenarios"; private const string AdminScenarios = "/__admin/scenarios";
private readonly RegexMatcher _adminMappingsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/mappings\/(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$"); private readonly RegexMatcher _adminMappingsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/mappings\/(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$");
private readonly RegexMatcher _adminRequestsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/requests\/(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$"); private readonly RegexMatcher _adminRequestsGuidPathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/requests\/(\{{0,1}([0-9a-fA-F]){8}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){4}-([0-9a-fA-F]){12}\}{0,1})$");
@@ -100,25 +101,39 @@ namespace WireMock.Server
} }
#endregion #endregion
#region StaticMappings #region StaticMappings
/// <summary>
/// Saves the static mappings.
/// </summary>
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
[PublicAPI]
public void SaveStaticMappings([CanBeNull] string folder = null)
{
foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface))
{
SaveMappingToFile(mapping, folder);
}
}
/// <summary> /// <summary>
/// Reads the static mappings from a folder. /// Reads the static mappings from a folder.
/// </summary> /// </summary>
/// <param name="folder">The optional folder. If not defined, use \__admin\mappings\</param> /// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
[PublicAPI] [PublicAPI]
public void ReadStaticMappings([CanBeNull] string folder = null) public void ReadStaticMappings([CanBeNull] string folder = null)
{ {
if (folder == null) if (folder == null)
{ {
folder = Path.Combine(Directory.GetCurrentDirectory(), AdminMappingsFolder); folder = _fileSystemHandler.GetMappingFolder();
} }
if (!Directory.Exists(folder)) if (!_fileSystemHandler.FolderExists(folder))
{ {
_logger.Info("The Static Mapping folder '{0}' does not exist, reading Static MappingFiles will be skipped.", folder);
return; return;
} }
foreach (string filename in Directory.EnumerateFiles(folder).OrderBy(f => f)) foreach (string filename in _fileSystemHandler.EnumerateFiles(folder).OrderBy(f => f))
{ {
_logger.Info("Reading Static MappingFile : '{0}'", filename); _logger.Info("Reading Static MappingFile : '{0}'", filename);
@@ -136,16 +151,16 @@ namespace WireMock.Server
/// <summary> /// <summary>
/// Watches the static mappings for changes. /// Watches the static mappings for changes.
/// </summary> /// </summary>
/// <param name="folder">The optional folder. If not defined, use \__admin\mappings\</param> /// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
[PublicAPI] [PublicAPI]
public void WatchStaticMappings([CanBeNull] string folder = null) public void WatchStaticMappings([CanBeNull] string folder = null)
{ {
if (folder == null) if (folder == null)
{ {
folder = Path.Combine(Directory.GetCurrentDirectory(), AdminMappingsFolder); folder = _fileSystemHandler.GetMappingFolder();
} }
if (!Directory.Exists(folder)) if (!_fileSystemHandler.FolderExists(folder))
{ {
return; return;
} }
@@ -192,7 +207,7 @@ namespace WireMock.Server
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(path); string filenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
MappingModel mappingModel = JsonConvert.DeserializeObject<MappingModel>(FileHelper.ReadAllText(path)); MappingModel mappingModel = JsonConvert.DeserializeObject<MappingModel>(_fileSystemHandler.ReadMappingFile(path));
if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename)) if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
{ {
DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path); DeserializeAndAddOrUpdateMapping(mappingModel, guidFromFilename, path);
@@ -345,29 +360,31 @@ namespace WireMock.Server
#region Mappings #region Mappings
private ResponseMessage MappingsSave(RequestMessage requestMessage) private ResponseMessage MappingsSave(RequestMessage requestMessage)
{ {
foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface)) SaveStaticMappings();
{
SaveMappingToFile(mapping);
}
return ResponseMessageBuilder.Create("Mappings saved to disk"); return ResponseMessageBuilder.Create("Mappings saved to disk");
} }
private void SaveMappingToFile(Mapping mapping) private void SaveMappingToFile(Mapping mapping, string folder = null)
{ {
string folder = Path.Combine(Directory.GetCurrentDirectory(), AdminMappingsFolder); if (folder == null)
if (!Directory.Exists(folder))
{ {
Directory.CreateDirectory(folder); folder = _fileSystemHandler.GetMappingFolder();
}
if (!_fileSystemHandler.FolderExists(folder))
{
_fileSystemHandler.CreateFolder(folder);
} }
var model = MappingConverter.ToMappingModel(mapping); var model = MappingConverter.ToMappingModel(mapping);
string filename = !string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToString(); string filename = (!string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToString()) + ".json";
string filePath = Path.Combine(folder, filename + ".json"); string path = Path.Combine(folder, filename);
_logger.Info("Saving Mapping to file {0}", filePath);
File.WriteAllText(filePath, JsonConvert.SerializeObject(model, _settings)); _logger.Info("Saving Mapping file {0}", filename);
_fileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, _settings));
} }
private static string SanitizeFileName(string name, char replaceChar = '_') private static string SanitizeFileName(string name, char replaceChar = '_')

View File

@@ -1,11 +1,12 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json;
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using Newtonsoft.Json;
using WireMock.Handlers;
using WireMock.Http; using WireMock.Http;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Matchers; using WireMock.Matchers;
@@ -14,7 +15,6 @@ using WireMock.Owin;
using WireMock.RequestBuilders; using WireMock.RequestBuilders;
using WireMock.ResponseProviders; using WireMock.ResponseProviders;
using WireMock.Settings; using WireMock.Settings;
using WireMock.Transformers;
using WireMock.Validation; using WireMock.Validation;
namespace WireMock.Server namespace WireMock.Server
@@ -25,6 +25,8 @@ namespace WireMock.Server
public partial class FluentMockServer : IDisposable public partial class FluentMockServer : IDisposable
{ {
private readonly IWireMockLogger _logger; private readonly IWireMockLogger _logger;
private readonly IFileSystemHandler _fileSystemHandler;
private const int ServerStartDelay = 100; private const int ServerStartDelay = 100;
private readonly IOwinSelfHost _httpServer; private readonly IOwinSelfHost _httpServer;
private readonly WireMockMiddlewareOptions _options = new WireMockMiddlewareOptions(); private readonly WireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
@@ -183,7 +185,9 @@ namespace WireMock.Server
private FluentMockServer(IFluentMockServerSettings settings) private FluentMockServer(IFluentMockServerSettings settings)
{ {
settings.Logger = settings.Logger ?? new WireMockConsoleLogger(); settings.Logger = settings.Logger ?? new WireMockConsoleLogger();
_logger = settings.Logger; _logger = settings.Logger;
_fileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
_logger.Info("WireMock.Net by Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)"); _logger.Info("WireMock.Net by Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
_logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented)); _logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));

View File

@@ -1,6 +1,7 @@
using System; using System;
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using WireMock.Handlers;
using WireMock.Logging; using WireMock.Logging;
namespace WireMock.Settings namespace WireMock.Settings
@@ -77,5 +78,10 @@ namespace WireMock.Settings
[PublicAPI] [PublicAPI]
[JsonIgnore] [JsonIgnore]
public IWireMockLogger Logger { get; set; } = new WireMockNullLogger(); public IWireMockLogger Logger { get; set; } = new WireMockNullLogger();
/// <inheritdoc cref="IFluentMockServerSettings.FileSystemHandler"/>
[PublicAPI]
[JsonIgnore]
public IFileSystemHandler FileSystemHandler { get; set; } = new LocalFileSystemHandler();
} }
} }

View File

@@ -1,5 +1,6 @@
using System; using System;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Handlers;
using WireMock.Logging; using WireMock.Logging;
namespace WireMock.Settings namespace WireMock.Settings
@@ -105,5 +106,11 @@ namespace WireMock.Settings
/// </summary> /// </summary>
[PublicAPI] [PublicAPI]
IWireMockLogger Logger { get; set; } IWireMockLogger Logger { get; set; }
/// <summary>
/// Handler to interact with the file system to read and write static mapping files.
/// </summary>
[PublicAPI]
IFileSystemHandler FileSystemHandler { get; set; }
} }
} }

View File

@@ -1,5 +1,8 @@
using System.IO; using System.IO;
using System.Threading; using System.Threading;
using JetBrains.Annotations;
using WireMock.Handlers;
using WireMock.Validation;
namespace WireMock.Util namespace WireMock.Util
{ {
@@ -8,17 +11,19 @@ namespace WireMock.Util
private const int NumberOfRetries = 3; private const int NumberOfRetries = 3;
private const int DelayOnRetry = 500; private const int DelayOnRetry = 500;
public static string ReadAllText(string path) public static string ReadAllTextWithRetryAndDelay([NotNull] IFileSystemHandler filehandler, [NotNull] string path)
{ {
Check.NotNull(filehandler, nameof(filehandler));
Check.NotNullOrEmpty(path, nameof(path));
for (int i = 1; i <= NumberOfRetries; ++i) for (int i = 1; i <= NumberOfRetries; ++i)
{ {
try try
{ {
return File.ReadAllText(path); return filehandler.ReadMappingFile(path);
} }
catch catch
{ {
// You may check error code to filter some exceptions, not every error can be recovered.
Thread.Sleep(DelayOnRetry); Thread.Sleep(DelayOnRetry);
} }
} }

View File

@@ -3,7 +3,7 @@
<PropertyGroup> <PropertyGroup>
<Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description> <Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description>
<AssemblyTitle>WireMock.Net</AssemblyTitle> <AssemblyTitle>WireMock.Net</AssemblyTitle>
<Version>1.0.4.9</Version> <Version>1.0.4.10</Version>
<Authors>Stef Heyenrath</Authors> <Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks> <TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>

View File

@@ -7,6 +7,7 @@ using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using Moq;
using NFluent; using NFluent;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.RequestBuilders; using WireMock.RequestBuilders;
@@ -14,6 +15,10 @@ using WireMock.ResponseBuilders;
using WireMock.Server; using WireMock.Server;
using Xunit; using Xunit;
using Newtonsoft.Json; using Newtonsoft.Json;
using WireMock.Handlers;
using WireMock.Logging;
using WireMock.Settings;
using WireMock.Admin.Mappings;
namespace WireMock.Net.Tests namespace WireMock.Net.Tests
{ {
@@ -42,6 +47,35 @@ namespace WireMock.Net.Tests
server2.Stop(); server2.Stop();
} }
[Fact]
public void FluentMockServer_SaveStaticMappings()
{
// Assign
string guid = "791a3f31-6946-aaaa-8e6f-0237c7441111";
var _staticMappingHandlerMock = new Mock<IFileSystemHandler>();
_staticMappingHandlerMock.Setup(m => m.GetMappingFolder()).Returns("folder");
_staticMappingHandlerMock.Setup(m => m.FolderExists(It.IsAny<string>())).Returns(true);
_staticMappingHandlerMock.Setup(m => m.WriteMappingFile(It.IsAny<string>(), It.IsAny<string>()));
_server = FluentMockServer.Start(new FluentMockServerSettings
{
FileSystemHandler = _staticMappingHandlerMock.Object
});
_server
.Given(Request.Create().WithPath($"/foo_{Guid.NewGuid()}"))
.WithGuid(guid)
.RespondWith(Response.Create().WithBody("save test"));
// Act
_server.SaveStaticMappings();
// Assert and Verify
_staticMappingHandlerMock.Verify(m => m.GetMappingFolder(), Times.Once);
_staticMappingHandlerMock.Verify(m => m.FolderExists("folder"), Times.Once);
_staticMappingHandlerMock.Verify(m => m.WriteMappingFile(Path.Combine("folder", guid + ".json"), It.IsAny<string>()), Times.Once);
}
[Fact] [Fact]
public void FluentMockServer_ReadStaticMapping_WithNonGuidFilename() public void FluentMockServer_ReadStaticMapping_WithNonGuidFilename()
{ {
@@ -108,6 +142,49 @@ namespace WireMock.Net.Tests
Check.That(mappings.First().Title).IsNullOrEmpty(); Check.That(mappings.First().Title).IsNullOrEmpty();
} }
[Fact]
public void FluentMockServer_ReadStaticMappings_FolderExistsIsTrue()
{
// Assign
var _staticMappingHandlerMock = new Mock<IFileSystemHandler>();
_staticMappingHandlerMock.Setup(m => m.GetMappingFolder()).Returns("folder");
_staticMappingHandlerMock.Setup(m => m.FolderExists(It.IsAny<string>())).Returns(true);
_staticMappingHandlerMock.Setup(m => m.EnumerateFiles(It.IsAny<string>())).Returns(new string[0]);
_server = FluentMockServer.Start(new FluentMockServerSettings
{
FileSystemHandler = _staticMappingHandlerMock.Object
});
// Act
_server.ReadStaticMappings();
// Assert and Verify
_staticMappingHandlerMock.Verify(m => m.GetMappingFolder(), Times.Once);
_staticMappingHandlerMock.Verify(m => m.FolderExists("folder"), Times.Once);
_staticMappingHandlerMock.Verify(m => m.EnumerateFiles("folder"), Times.Once);
}
[Fact]
public void FluentMockServer_ReadStaticMappingAndAddOrUpdate()
{
// Assign
string mapping = "{\"Request\": {\"Path\": {\"Matchers\": [{\"Name\": \"WildcardMatcher\",\"Pattern\": \"/static/mapping\"}]},\"Methods\": [\"get\"]},\"Response\": {\"BodyAsJson\": { \"body\": \"static mapping\" }}}";
var _staticMappingHandlerMock = new Mock<IFileSystemHandler>();
_staticMappingHandlerMock.Setup(m => m.ReadMappingFile(It.IsAny<string>())).Returns(mapping);
_server = FluentMockServer.Start(new FluentMockServerSettings
{
FileSystemHandler = _staticMappingHandlerMock.Object
});
// Act
_server.ReadStaticMappingAndAddOrUpdate(@"c:\test.json");
// Assert and Verify
_staticMappingHandlerMock.Verify(m => m.ReadMappingFile(@"c:\test.json"), Times.Once);
}
[Fact] [Fact]
public void FluentMockServer_ReadStaticMappings() public void FluentMockServer_ReadStaticMappings()
{ {
@@ -142,7 +219,7 @@ namespace WireMock.Net.Tests
string guid = "90356dba-b36c-469a-a17e-669cd84f1f05"; string guid = "90356dba-b36c-469a-a17e-669cd84f1f05";
_server = FluentMockServer.Start(); _server = FluentMockServer.Start();
_server.Given(Request.Create().WithPath("/foo1").UsingGet()).WithGuid(guid) _server.Given(Request.Create().WithPath("/foo100").UsingGet()).WithGuid(guid)
.RespondWith(Response.Create().WithStatusCode(201).WithBody("1")); .RespondWith(Response.Create().WithStatusCode(201).WithBody("1"));
var mappings = _server.Mappings.ToArray(); var mappings = _server.Mappings.ToArray();
@@ -219,13 +296,14 @@ namespace WireMock.Net.Tests
public async Task FluentMockServer_Should_respond_to_request_methodPatch() public async Task FluentMockServer_Should_respond_to_request_methodPatch()
{ {
// given // given
string path = $"/foo_{Guid.NewGuid()}";
_server = FluentMockServer.Start(); _server = FluentMockServer.Start();
_server.Given(Request.Create().WithPath("/foo").UsingMethod("patch")) _server.Given(Request.Create().WithPath(path).UsingMethod("patch"))
.RespondWith(Response.Create().WithBody("hello patch")); .RespondWith(Response.Create().WithBody("hello patch"));
// when // when
var msg = new HttpRequestMessage(new HttpMethod("patch"), new Uri("http://localhost:" + _server.Ports[0] + "/foo")) var msg = new HttpRequestMessage(new HttpMethod("patch"), new Uri("http://localhost:" + _server.Ports[0] + path))
{ {
Content = new StringContent("{\"data\": {\"attr\":\"value\"}}") Content = new StringContent("{\"data\": {\"attr\":\"value\"}}")
}; };
@@ -338,13 +416,14 @@ namespace WireMock.Net.Tests
public async Task FluentMockServer_Should_respond_to_request_bodyAsBytes() public async Task FluentMockServer_Should_respond_to_request_bodyAsBytes()
{ {
// given // given
string path = $"/foo_{Guid.NewGuid()}";
_server = FluentMockServer.Start(); _server = FluentMockServer.Start();
_server.Given(Request.Create().WithPath("/foo").UsingGet()).RespondWith(Response.Create().WithBody(new byte[] { 48, 49 })); _server.Given(Request.Create().WithPath(path).UsingGet()).RespondWith(Response.Create().WithBody(new byte[] { 48, 49 }));
// when // when
var responseAsString = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo"); var responseAsString = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + path);
var responseAsBytes = await new HttpClient().GetByteArrayAsync("http://localhost:" + _server.Ports[0] + "/foo"); var responseAsBytes = await new HttpClient().GetByteArrayAsync("http://localhost:" + _server.Ports[0] + path);
// then // then
Check.That(responseAsString).IsEqualTo("01"); Check.That(responseAsString).IsEqualTo("01");
@@ -371,13 +450,14 @@ namespace WireMock.Net.Tests
foreach (var item in validMatchersForHelloServerJsonMessage) foreach (var item in validMatchersForHelloServerJsonMessage)
{ {
string path = $"/foo_{Guid.NewGuid()}";
_server _server
.Given(Request.Create().WithPath("/foo").WithBody((IMatcher)item[0])) .Given(Request.Create().WithPath(path).WithBody((IMatcher)item[0]))
.RespondWith(Response.Create().WithBody("Hello client")); .RespondWith(Response.Create().WithBody("Hello client"));
// Act // Act
var content = new StringContent(jsonRequestMessage, Encoding.UTF8, (string)item[1]); var content = new StringContent(jsonRequestMessage, Encoding.UTF8, (string)item[1]);
var response = await new HttpClient().PostAsync("http://localhost:" + _server.Ports[0] + "/foo", content); var response = await new HttpClient().PostAsync("http://localhost:" + _server.Ports[0] + path, content);
// Assert // Assert
var responseString = await response.Content.ReadAsStringAsync(); var responseString = await response.Content.ReadAsStringAsync();
@@ -392,10 +472,11 @@ namespace WireMock.Net.Tests
public async Task FluentMockServer_Should_respond_404_for_unexpected_request() public async Task FluentMockServer_Should_respond_404_for_unexpected_request()
{ {
// given // given
string path = $"/foo{Guid.NewGuid()}";
_server = FluentMockServer.Start(); _server = FluentMockServer.Start();
// when // when
var response = await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo"); var response = await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + path);
// then // then
Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.NotFound); Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.NotFound);
@@ -405,20 +486,21 @@ namespace WireMock.Net.Tests
[Fact] [Fact]
public async Task FluentMockServer_Should_find_a_request_satisfying_a_request_spec() public async Task FluentMockServer_Should_find_a_request_satisfying_a_request_spec()
{ {
// given // Assign
string path = $"/bar_{Guid.NewGuid()}";
_server = FluentMockServer.Start(); _server = FluentMockServer.Start();
// when // when
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo"); await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/foo");
await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + "/bar"); await new HttpClient().GetAsync("http://localhost:" + _server.Ports[0] + path);
// then // then
var result = _server.FindLogEntries(Request.Create().WithPath(new RegexMatcher("^/b.*"))).ToList(); var result = _server.FindLogEntries(Request.Create().WithPath(new RegexMatcher("^/b.*"))).ToList();
Check.That(result).HasSize(1); Check.That(result).HasSize(1);
var requestLogged = result.First(); var requestLogged = result.First();
Check.That(requestLogged.RequestMessage.Path).IsEqualTo("/bar"); Check.That(requestLogged.RequestMessage.Path).IsEqualTo(path);
Check.That(requestLogged.RequestMessage.Url).IsEqualTo("http://localhost:" + _server.Ports[0] + "/bar"); Check.That(requestLogged.RequestMessage.Url).IsEqualTo("http://localhost:" + _server.Ports[0] + path);
} }
[Fact] [Fact]
@@ -439,11 +521,12 @@ namespace WireMock.Net.Tests
public void FluentMockServer_Should_reset_mappings() public void FluentMockServer_Should_reset_mappings()
{ {
// given // given
string path = $"/foo_{Guid.NewGuid()}";
_server = FluentMockServer.Start(); _server = FluentMockServer.Start();
_server _server
.Given(Request.Create() .Given(Request.Create()
.WithPath("/foo") .WithPath(path)
.UsingGet()) .UsingGet())
.RespondWith(Response.Create() .RespondWith(Response.Create()
.WithBody(@"{ msg: ""Hello world!""}")); .WithBody(@"{ msg: ""Hello world!""}"));
@@ -453,35 +536,38 @@ namespace WireMock.Net.Tests
// then // then
Check.That(_server.Mappings).IsEmpty(); Check.That(_server.Mappings).IsEmpty();
Check.ThatAsyncCode(() => new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo")) Check.ThatAsyncCode(() => new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + path))
.ThrowsAny(); .ThrowsAny();
} }
[Fact] [Fact]
public async Task FluentMockServer_Should_respond_a_redirect_without_body() public async Task FluentMockServer_Should_respond_a_redirect_without_body()
{ {
// given // Assign
string path = $"/foo_{Guid.NewGuid()}";
string pathToRedirect = $"/bar_{Guid.NewGuid()}";
_server = FluentMockServer.Start(); _server = FluentMockServer.Start();
_server _server
.Given(Request.Create() .Given(Request.Create()
.WithPath("/foo") .WithPath(path)
.UsingGet()) .UsingGet())
.RespondWith(Response.Create() .RespondWith(Response.Create()
.WithStatusCode(307) .WithStatusCode(307)
.WithHeader("Location", "/bar")); .WithHeader("Location", pathToRedirect));
_server _server
.Given(Request.Create() .Given(Request.Create()
.WithPath("/bar") .WithPath(pathToRedirect)
.UsingGet()) .UsingGet())
.RespondWith(Response.Create() .RespondWith(Response.Create()
.WithStatusCode(200) .WithStatusCode(200)
.WithBody("REDIRECT SUCCESSFUL")); .WithBody("REDIRECT SUCCESSFUL"));
// when // Act
var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo"); var response = await new HttpClient().GetStringAsync($"http://localhost:{_server.Ports[0]}{path}");
// then // Assert
Check.That(response).IsEqualTo("REDIRECT SUCCESSFUL"); Check.That(response).IsEqualTo("REDIRECT SUCCESSFUL");
} }

View File

@@ -1,4 +1,5 @@
using System.Linq; using System;
using System.Linq;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
@@ -16,16 +17,17 @@ namespace WireMock.Net.Tests
public async Task Scenarios_Should_skip_non_relevant_states() public async Task Scenarios_Should_skip_non_relevant_states()
{ {
// given // given
string path = $"/foo_{Guid.NewGuid()}";
var server = FluentMockServer.Start(); var server = FluentMockServer.Start();
server server
.Given(Request.Create().WithPath("/foo").UsingGet()) .Given(Request.Create().WithPath(path).UsingGet())
.InScenario("s") .InScenario("s")
.WhenStateIs("Test state") .WhenStateIs("Test state")
.RespondWith(Response.Create()); .RespondWith(Response.Create());
// when // when
var response = await new HttpClient().GetAsync("http://localhost:" + server.Ports[0] + "/foo"); var response = await new HttpClient().GetAsync("http://localhost:" + server.Ports[0] + path);
// then // then
Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.NotFound); Check.That(response.StatusCode).IsEqualTo(HttpStatusCode.NotFound);
@@ -37,23 +39,24 @@ namespace WireMock.Net.Tests
public async Task Scenarios_Should_process_request_if_equals_state_and_single_state_defined() public async Task Scenarios_Should_process_request_if_equals_state_and_single_state_defined()
{ {
// given // given
string path = $"/foo_{Guid.NewGuid()}";
var server = FluentMockServer.Start(); var server = FluentMockServer.Start();
server server
.Given(Request.Create().WithPath("/foo").UsingGet()) .Given(Request.Create().WithPath(path).UsingGet())
.InScenario("s") .InScenario("s")
.WillSetStateTo("Test state") .WillSetStateTo("Test state")
.RespondWith(Response.Create().WithBody("No state msg")); .RespondWith(Response.Create().WithBody("No state msg"));
server server
.Given(Request.Create().WithPath("/foo").UsingGet()) .Given(Request.Create().WithPath(path).UsingGet())
.InScenario("s") .InScenario("s")
.WhenStateIs("Test state") .WhenStateIs("Test state")
.RespondWith(Response.Create().WithBody("Test state msg")); .RespondWith(Response.Create().WithBody("Test state msg"));
// when // when
var responseNoState = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/foo"); var responseNoState = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + path);
var responseWithState = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + "/foo"); var responseWithState = await new HttpClient().GetStringAsync("http://localhost:" + server.Ports[0] + path);
// then // then
Check.That(responseNoState).Equals("No state msg"); Check.That(responseNoState).Equals("No state msg");

View File

@@ -0,0 +1,44 @@
using System;
using System.IO;
using Moq;
using NFluent;
using WireMock.Handlers;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.Util
{
public class FileHelperTests
{
[Fact]
public void FileHelper_ReadAllTextWithRetryAndDelay()
{
// Assign
var _staticMappingHandlerMock = new Mock<IFileSystemHandler>();
_staticMappingHandlerMock.Setup(m => m.ReadMappingFile(It.IsAny<string>())).Returns("text");
// Act
string result = FileHelper.ReadAllTextWithRetryAndDelay(_staticMappingHandlerMock.Object, @"c:\temp");
// Assert
Check.That(result).Equals("text");
// Verify
_staticMappingHandlerMock.Verify(m => m.ReadMappingFile(@"c:\temp"), Times.Once);
}
[Fact]
public void FileHelper_ReadAllTextWithRetryAndDelay_Throws()
{
// Assign
var _staticMappingHandlerMock = new Mock<IFileSystemHandler>();
_staticMappingHandlerMock.Setup(m => m.ReadMappingFile(It.IsAny<string>())).Throws<NotSupportedException>();
// Act
Check.ThatCode(() => FileHelper.ReadAllTextWithRetryAndDelay(_staticMappingHandlerMock.Object, @"c:\temp")).Throws<IOException>();
// Verify
_staticMappingHandlerMock.Verify(m => m.ReadMappingFile(@"c:\temp"), Times.Exactly(3));
}
}
}