Compare commits

...

25 Commits

Author SHA1 Message Date
Stef Heyenrath
c7ad8469a3 1.0.3.9 (#108) 2018-03-15 22:18:35 +01:00
Stef Heyenrath
b7dd1b9242 Merge branch 'stef_increase_code_coverage' 2018-03-15 22:14:52 +01:00
Stef Heyenrath
82fdce4605 fix contentTypeHeader 2018-03-15 22:14:34 +01:00
Stef Heyenrath
15500a812c Add some more tests 2018-03-14 21:24:20 +01:00
Stef Heyenrath
c2183ab40c Increase code coverage (#107) 2018-03-13 22:04:43 +01:00
Stef Heyenrath
83d71bb24e More fixes for #106 2018-03-11 12:18:27 +01:00
Stef Heyenrath
ff012be173 Fixed #106 2018-03-10 15:50:34 +01:00
Stef Heyenrath
f604be3c02 Add logger to WireMock WebApp 2018-03-10 14:53:50 +01:00
Stef Heyenrath
8d109c69eb Fix #104 2018-03-09 08:20:48 +01:00
Stef Heyenrath
3e634c2fde Example : WireMock.Net.StandAlone.Net461 (#104) 2018-03-08 18:28:53 +01:00
Stef Heyenrath
9b5a482b8d Also handle application/x-www-form-urlencoded as string body 2018-03-08 11:00:19 +01:00
Stef Heyenrath
e18fffb661 release notes 2018-03-04 11:30:50 +01:00
Stef Heyenrath
a2df91a2a2 1.0.3.4 2018-03-04 10:50:30 +01:00
Stef Heyenrath
1442e874cf Remove codecov.io 2018-03-04 10:34:07 +01:00
Alastair Crabtree
3f2c139f90 feat: add WithBody(req => dostuff) style callback (#102) 2018-03-03 08:38:03 +00:00
Stef Heyenrath
2b8a58c68c #100 2018-03-02 14:35:10 +01:00
Stef Heyenrath
977d91109e ICallbackResponseBuilder + added more unit-tests (#101)
* Callback

* Add more tests
2018-03-02 09:12:36 +00:00
Stef Heyenrath
22298114d7 Fix ResponseMessageTransformer 2018-02-28 18:05:10 +01:00
Stef Heyenrath
0be8ee1174 Fix ResponseMessageTransformer (BodyAsJson) 2018-02-28 09:24:27 +01:00
Stef Heyenrath
17741cbc50 FIx for IsStarted (#93) 2018-02-28 08:34:57 +01:00
Stef Heyenrath
938d3fb095 Replace log4net by custom logger (#94) (#96)
* Replace log4net by custom logger

* WireMockNullLogger
2018-02-28 07:01:03 +00:00
Stef Heyenrath
e850126184 Unittest fix (#95)
* fix tests

* fix tests
2018-02-27 11:17:36 +00:00
Stef Heyenrath
ad6c59e3b5 1.0.3.3 2018-02-24 09:04:21 +01:00
Stef Heyenrath
0c25b2e9f2 Json fixes (#91) (#92)
* Fixes for JsonPath

* More tests

* Fixes + added tests
2018-02-23 12:29:43 +00:00
Stef Heyenrath
1ffd56701c fix unit-test 2018-02-14 20:38:19 +01:00
107 changed files with 3047 additions and 1114 deletions

View File

@@ -1,3 +1,48 @@
# 1.0.3.9 (15 March 2018)
- [#108](https://github.com/WireMock-Net/WireMock.Net/issues/108) - Issue: provide correct contentTypeHeader value for the bodyparser +fix
Commits: f604be3c02...b7dd1b9242
# 1.0.3.8 (10 March 2018)
- [#106](https://github.com/WireMock-Net/WireMock.Net/issues/106) - Issue: Params does not work, when there are multiple values for a key
Commits: f604be3c02...f604be3c02
# 1.0.3.7 (09 March 2018)
- [#104](https://github.com/WireMock-Net/WireMock.Net/issues/104) - Issue: PlatformNotSupportedException
Commits: 3e634c2fde...3e634c2fde
# 1.0.3.4 (04 March 2018)
- [#102](https://github.com/WireMock-Net/WireMock.Net/pull/102) - Feature: add WithBody(req => dostuff) style callback contributed by Alastair Crabtree ([alastairtree](https://github.com/alastairtree)) +feature
- [#101](https://github.com/WireMock-Net/WireMock.Net/pull/101) - ICallbackResponseBuilder + added more unit-tests contributed by Stef Heyenrath ([StefH](https://github.com/StefH)) +fix
- [#100](https://github.com/WireMock-Net/WireMock.Net/issues/100) - Question: JsonPathMatcher - not working for rootless jsons?
- [#99](https://github.com/WireMock-Net/WireMock.Net/pull/99) - feat: simple implementation/spike of dynamic responses using callbacks contributed by Stef Heyenrath ([StefH](https://github.com/StefH))
- [#98](https://github.com/WireMock-Net/WireMock.Net/issues/98) - IBodyResponseBuilder.WithBody* should receive the request as a parameter
- [#96](https://github.com/WireMock-Net/WireMock.Net/pull/96) - Replace log4net by custom logger (#94) contributed by Stef Heyenrath ([StefH](https://github.com/StefH))
- [#95](https://github.com/WireMock-Net/WireMock.Net/pull/95) - Unittest fix contributed by Stef Heyenrath ([StefH](https://github.com/StefH))
- [#94](https://github.com/WireMock-Net/WireMock.Net/issues/94) - Issue: Introduced dependency on log4net
- [#93](https://github.com/WireMock-Net/WireMock.Net/issues/93) - Bug: FluentMockServer IsStarted after calling Start()
- [#66](https://github.com/WireMock-Net/WireMock.Net/issues/66) - Interested in callbacks?
Commits: e850126184...a2df91a2a2
# 1.0.3.3 (24 February 2018)
- [#92](https://github.com/WireMock-Net/WireMock.Net/pull/92) - Json fixes (#91) contributed by Stef Heyenrath ([StefH](https://github.com/StefH))
- [#91](https://github.com/WireMock-Net/WireMock.Net/issues/91) - Bug: WireMock.Net is not matching application/json http requests using JSONPathMatcher +fix
Commits: 1ffd56701c...ad6c59e3b5
# 1.0.3.2 (14 February 2018)
- [#90](https://github.com/WireMock-Net/WireMock.Net/pull/90) - Concurrent issue (#88) contributed by Stef Heyenrath ([StefH](https://github.com/StefH))
@@ -5,18 +50,10 @@
- [#88](https://github.com/WireMock-Net/WireMock.Net/issues/88) - Bug: Standalone server throws 500 error when receiving concurrent requests +fix
- [#87](https://github.com/WireMock-Net/WireMock.Net/issues/87) - Feature: Add logging
Commits: 51070dab63...693778659e
Commits: 51070dab63...4f87146622
# 1.0.3.1 (14 February 2018)
- [#89](https://github.com/WireMock-Net/WireMock.Net/pull/89) - Add log4net logging contributed by Stef Heyenrath ([StefH](https://github.com/StefH))
- [#87](https://github.com/WireMock-Net/WireMock.Net/issues/87) - Feature: Add logging
Commits: ...
# 1.0.3 (04 February 2018)
# 1.0.3.0 (05 February 2018)
- [#86](https://github.com/WireMock-Net/WireMock.Net/issues/86) - Feature : Add FileSystemWatcher logic for watching static mapping files +feature
- [#85](https://github.com/WireMock-Net/WireMock.Net/issues/85) - Bug: https for netstandard does not work ? +fix
@@ -25,7 +62,7 @@ Commits: ...
- [#81](https://github.com/WireMock-Net/WireMock.Net/issues/81) - Feature: When using proxy, only BodyAsBytes in case of binary data?
- [#80](https://github.com/WireMock-Net/WireMock.Net/issues/80) - Feature: When using proxy, in case Content-Type is JSON, use BodyAsJson in Response
Commits: 40ff8514ac...cf4e83b10b
Commits: 40ff8514ac...9778c5adbe
# 1.0.2.13 (23 January 2018)

Binary file not shown.

View File

@@ -1,5 +1,5 @@
https://github.com/GitTools/GitReleaseNotes
GitReleaseNotes.exe . /OutputFile CHANGELOG.md /Version 1.0.3.2
GitReleaseNotes.exe . /OutputFile CHANGELOG.md /Version 1.0.3.9
GitReleaseNotes.exe . /OutputFile CHANGELOG.md /allTags

View File

@@ -2,7 +2,6 @@
A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) which mimics the functionality from the JAVA based http://WireMock.org
[![Build status](https://ci.appveyor.com/api/projects/status/b3n6q3ygbww4lyls?svg=true)](https://ci.appveyor.com/project/StefH/wiremock-net)
[![codecov](https://codecov.io/gh/WireMock-Net/WireMock.Net/branch/master/graph/badge.svg)](https://codecov.io/gh/WireMock-Net/WireMock.Net)
[![Coverage Status](https://coveralls.io/repos/github/WireMock-Net/WireMock.Net/badge.svg?branch=master)](https://coveralls.io/github/WireMock-Net/WireMock.Net?branch=master)
[![GitHub issues](https://img.shields.io/github/issues/WireMock-Net/WireMock.Net.svg)](https://github.com/WireMock-Net/WireMock.Net/issues)
[![GitHub stars](https://img.shields.io/github/stars/WireMock-Net/WireMock.Net.svg)](https://github.com/WireMock-Net/WireMock.Net/stargazers)

View File

@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27130.2027
VisualStudioVersion = 15.0.27130.2036
MinimumVisualStudioVersion = 10.0.40219.1
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "src", "src", "{EF242EDF-7133-4277-9A0C-18744DE08707}"
EndProject
@@ -46,6 +46,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Proxy.
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Proxy.NETCoreApp2", "examples\WireMock.Net.Console.Proxy.NETCoreApp2\WireMock.Net.Console.Proxy.NETCoreApp2.csproj", "{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.StandAlone.Net461", "examples\WireMock.Net.StandAlone.Net461\WireMock.Net.StandAlone.Net461.csproj", "{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -100,6 +102,10 @@ Global
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Debug|Any CPU.Build.0 = Debug|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6}.Release|Any CPU.Build.0 = Release|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -117,6 +123,7 @@ Global
{049539C1-7A66-4559-AD7A-B1C73B97CBB0} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{26433A8F-BF01-4962-97EB-81BFFBB61096} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{23A9AA3C-40FC-42AA-8A5E-05899795A1C6} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65} = {F0C22C47-DF71-463C-9B04-B4E0F3B8708A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {BF428BCC-C837-433B-87D2-15C7014B73E9}

View File

@@ -0,0 +1,3 @@
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSL/@EntryIndexedValue">SSL</s:String></wpf:ResourceDictionary>

View File

@@ -41,6 +41,15 @@ namespace WireMock.Net.ConsoleApplication
// .RespondWith(Response.Create()
// .WithProxy("http://restcountries.eu"));
server
.Given(Request
.Create()
.WithPath("/jsonthings")
.WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]"))
.UsingPut())
.RespondWith(Response.Create()
.WithBody(@"{ ""result"": ""JsonPathMatcher !!!""}"));
server
.Given(Request
.Create()

View File

@@ -21,7 +21,7 @@ namespace WireMock.Net.StandAlone.NETCoreApp
{
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
_server = StandAloneApp.Start(args);
_server = StandAloneApp.Start(args, new WireMockLog4NetLogger());
Console.WriteLine($"{DateTime.UtcNow} Press Ctrl+C to shut down");
@@ -37,7 +37,7 @@ namespace WireMock.Net.StandAlone.NETCoreApp
while (true)
{
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server running");
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server running : {_server.IsStarted}");
Thread.Sleep(sleepTime);
}
}

View File

@@ -0,0 +1,30 @@
using log4net;
using WireMock.Logging;
namespace WireMock.Net.StandAlone.NETCoreApp
{
internal class WireMockLog4NetLogger : IWireMockLogger
{
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
public void Debug(string formatString, params object[] args)
{
Log.DebugFormat(formatString, args);
}
public void Info(string formatString, params object[] args)
{
Log.InfoFormat(formatString, args);
}
public void Warn(string formatString, params object[] args)
{
Log.WarnFormat(formatString, args);
}
public void Error(string formatString, params object[] args)
{
Log.ErrorFormat(formatString, args);
}
}
}

View File

@@ -0,0 +1,34 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.6.1" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-10.0.0.0" newVersion="10.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Owin" publicKeyToken="31bf3856ad364e35" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.2" newVersion="4.1.1.2" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Diagnostics.DiagnosticSource" publicKeyToken="cc7b13ffcd2ddd51" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="System.Security.Cryptography.X509Certificates" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.1.1.0" newVersion="4.1.1.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Microsoft.Win32.Primitives" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-4.0.1.0" newVersion="4.0.1.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -0,0 +1,19 @@
using System;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
namespace WireMock.Net.StandAlone.Net461
{
static class Program
{
static void Main(string[] args)
{
var server = StandAloneApp.Start(args);
server.Given(Request.Create())
.RespondWith(Response.Create().WithProxy("http://10.10.66.65"));
Console.WriteLine("Press any key to stop the server");
Console.ReadKey();
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("WireMock.Net.StandAlone.Net461")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WireMock.Net.StandAlone.Net461")]
[assembly: AssemblyCopyright("Copyright © Stef Heyenrath")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("3c279524-db73-4de3-bef1-f2b2958c9f65")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -0,0 +1,114 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>WireMock.Net.StandAlone.Net461</RootNamespace>
<AssemblyName>WireMock.Net.StandAlone.Net461</AssemblyName>
<TargetFrameworkVersion>v4.6.1</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>WireMock.Net.StandAlone.Net461.Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<Reference Include="Handlebars, Version=1.8.1.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.1.9.0\lib\net40\Handlebars.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.4.0.0\lib\net451\Microsoft.Owin.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Host.HttpListener, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Host.HttpListener.4.0.0\lib\net451\Microsoft.Owin.Host.HttpListener.dll</HintPath>
</Reference>
<Reference Include="Microsoft.Owin.Hosting, Version=4.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Hosting.4.0.0\lib\net451\Microsoft.Owin.Hosting.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=10.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.10.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
</Reference>
<Reference Include="RestEase, Version=1.4.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\RestEase.1.4.4\lib\net45\RestEase.dll</HintPath>
</Reference>
<Reference Include="SimMetrics.Net, Version=1.0.4.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\SimMetrics.Net.1.0.4\lib\net45\SimMetrics.Net.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Net.Http, Version=4.1.1.2, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Net.Http.4.3.3\lib\net46\System.Net.Http.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.Formatting, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.4\lib\net45\System.Net.Http.Formatting.dll</HintPath>
</Reference>
<Reference Include="System.Net.Http.WebRequest" />
<Reference Include="System.Numerics" />
<Reference Include="System.Security.Cryptography.Algorithms, Version=4.1.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.Algorithms.4.3.0\lib\net461\System.Security.Cryptography.Algorithms.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Encoding, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.Primitives, Version=4.0.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll</HintPath>
</Reference>
<Reference Include="System.Security.Cryptography.X509Certificates, Version=4.1.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Security.Cryptography.X509Certificates.4.3.0\lib\net461\System.Security.Cryptography.X509Certificates.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.Web.Http, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Core.5.2.4\lib\net45\System.Web.Http.dll</HintPath>
</Reference>
<Reference Include="System.Web.Http.Owin, Version=5.2.4.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Owin.5.2.4\lib\net45\System.Web.Http.Owin.dll</HintPath>
</Reference>
<Reference Include="System.Xml" />
<Reference Include="System.Xml.Linq" />
<Reference Include="WireMock.Net, Version=1.0.3.6, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\WireMock.Net.1.0.3.6\lib\net46\WireMock.Net.dll</HintPath>
</Reference>
<Reference Include="WireMock.Net.StandAlone, Version=1.0.3.6, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\WireMock.Net.StandAlone.1.0.3.6\lib\net46\WireMock.Net.StandAlone.dll</HintPath>
</Reference>
<Reference Include="XPath2, Version=1.0.5.1, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\XPath2.1.0.5.1\lib\net40\XPath2.dll</HintPath>
</Reference>
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -0,0 +1,23 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Handlebars.Net" version="1.9.0" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.2.4" targetFramework="net461" />
<package id="Microsoft.Owin" version="4.0.0" targetFramework="net461" />
<package id="Microsoft.Owin.Host.HttpListener" version="4.0.0" targetFramework="net461" />
<package id="Microsoft.Owin.Hosting" version="4.0.0" targetFramework="net461" />
<package id="Newtonsoft.Json" version="10.0.3" targetFramework="net461" />
<package id="Owin" version="1.0" targetFramework="net461" />
<package id="RestEase" version="1.4.4" targetFramework="net461" />
<package id="SimMetrics.Net" version="1.0.4" targetFramework="net461" />
<package id="System.Net.Http" version="4.3.3" targetFramework="net461" />
<package id="System.Security.Cryptography.Algorithms" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Encoding" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.Primitives" version="4.3.0" targetFramework="net461" />
<package id="System.Security.Cryptography.X509Certificates" version="4.3.0" targetFramework="net461" />
<package id="WireMock.Net" version="1.0.3.6" targetFramework="net461" />
<package id="WireMock.Net.StandAlone" version="1.0.3.6" targetFramework="net461" />
<package id="XPath2" version="1.0.5.1" targetFramework="net461" />
</packages>

View File

@@ -1,6 +1,7 @@
using System.Threading;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using WireMock.Logging;
using WireMock.Net.StandAlone;
using WireMock.Settings;
@@ -13,10 +14,42 @@ namespace WireMock.Net.WebApplication
private readonly ILogger _logger;
private readonly IFluentMockServerSettings _settings;
private class Logger : IWireMockLogger
{
private readonly ILogger _logger;
public Logger(ILogger logger)
{
_logger = logger;
}
public void Debug(string formatString, params object[] args)
{
_logger.LogDebug(formatString, args);
}
public void Info(string formatString, params object[] args)
{
_logger.LogInformation(formatString, args);
}
public void Warn(string formatString, params object[] args)
{
_logger.LogWarning(formatString, args);
}
public void Error(string formatString, params object[] args)
{
_logger.LogError(formatString, args);
}
}
public WireMockService(ILogger logger, IFluentMockServerSettings settings)
{
_logger = logger;
_settings = settings;
_settings.Logger = new Logger(logger);
}
public void Run()

View File

@@ -14,7 +14,7 @@
},
"FluentMockServerSettings": {
"AdminUsername": "a",
"AdminPassword": "a",
"AdminPassword": "b",
"StartAdminInterface": true
}
}

View File

@@ -3,7 +3,7 @@ using WireMock.Server;
using WireMock.Settings;
using WireMock.Validation;
using JetBrains.Annotations;
using log4net;
using WireMock.Logging;
namespace WireMock.Net.StandAlone
{
@@ -12,8 +12,6 @@ namespace WireMock.Net.StandAlone
/// </summary>
public static class StandAloneApp
{
private static readonly ILog Log = LogManager.GetLogger(typeof(StandAloneApp));
/// <summary>
/// Start WireMock.Net standalone Server based on the FluentMockServerSettings.
/// </summary>
@@ -30,13 +28,12 @@ namespace WireMock.Net.StandAlone
/// Start WireMock.Net standalone Server based on the commandline arguments.
/// </summary>
/// <param name="args">The commandline arguments</param>
/// <param name="logger">The logger</param>
[PublicAPI]
public static FluentMockServer Start([NotNull] string[] args)
public static FluentMockServer Start([NotNull] string[] args, [CanBeNull] IWireMockLogger logger = null)
{
Check.NotNull(args, nameof(args));
Log.DebugFormat("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
var parser = new SimpleCommandLineParser();
parser.Parse(args);
@@ -52,6 +49,11 @@ namespace WireMock.Net.StandAlone
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
};
if (logger != null)
{
settings.Logger = logger;
}
if (parser.Contains("Port"))
{
settings.Port = parser.GetIntValue("Port");
@@ -74,9 +76,11 @@ namespace WireMock.Net.StandAlone
};
}
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
FluentMockServer server = Start(settings);
Log.InfoFormat("WireMock.Net server listening at {0}", string.Join(",", server.Urls));
settings.Logger.Info("WireMock.Net server listening at {0}", string.Join(",", server.Urls));
return server;
}

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Description>Lightweight StandAlone Http Mocking Server for .Net.</Description>
<AssemblyTitle>WireMock.Net.StandAlone</AssemblyTitle>
<Version>1.0.3.2</Version>
<Version>1.0.3.9</Version>
<Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -36,7 +36,6 @@
<PackageReference Include="JetBrains.Annotations" Version="10.4.0">
<PrivateAssets>All</PrivateAssets>
</PackageReference>
<PackageReference Include="log4net" Version="2.0.8" />
</ItemGroup>
<ItemGroup>

View File

@@ -8,33 +8,21 @@
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>
/// The name.
/// </value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the pattern.
/// </summary>
/// <value>
/// The pattern.
/// </value>
public string Pattern { get; set; }
/// <summary>
/// Gets or sets the patterns.
/// </summary>
/// <value>
/// The patterns.
/// </value>
public string[] Patterns { get; set; }
/// <summary>
/// Gets or sets the ignore case.
/// </summary>
/// <value>
/// The ignore case.
/// </value>
public bool? IgnoreCase { get; set; }
}
}

View File

@@ -1,62 +0,0 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.Validation;
using WireMock.Settings;
namespace WireMock
{
internal class DynamicResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, ResponseMessage> _responseMessageFunc;
public DynamicResponseProvider([NotNull] Func<RequestMessage, ResponseMessage> responseMessageFunc)
{
Check.NotNull(responseMessageFunc, nameof(responseMessageFunc));
_responseMessageFunc = responseMessageFunc;
}
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
{
return Task.FromResult(_responseMessageFunc(requestMessage));
}
}
internal class DynamicAsyncResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, Task<ResponseMessage>> _responseMessageFunc;
public DynamicAsyncResponseProvider([NotNull] Func<RequestMessage, Task<ResponseMessage>> responseMessageFunc)
{
Check.NotNull(responseMessageFunc, nameof(responseMessageFunc));
_responseMessageFunc = responseMessageFunc;
}
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
{
return _responseMessageFunc(requestMessage);
}
}
internal class ProxyAsyncResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, IProxyAndRecordSettings, Task<ResponseMessage>> _responseMessageFunc;
private readonly IProxyAndRecordSettings _settings;
public ProxyAsyncResponseProvider([NotNull] Func<RequestMessage, IProxyAndRecordSettings, Task<ResponseMessage>> responseMessageFunc, [NotNull] IProxyAndRecordSettings settings)
{
Check.NotNull(responseMessageFunc, nameof(responseMessageFunc));
Check.NotNull(settings, nameof(settings));
_responseMessageFunc = responseMessageFunc;
_settings = settings;
}
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
{
return _responseMessageFunc(requestMessage, _settings);
}
}
}

View File

@@ -16,7 +16,7 @@ namespace WireMock.Http
{
public static HttpClient CreateHttpClient(string clientX509Certificate2ThumbprintOrSubjectName = null)
{
#if NETSTANDARD || NET46
#if NETSTANDARD
var handler = new HttpClientHandler
{
CheckCertificateRevocationList = false,
@@ -24,12 +24,20 @@ namespace WireMock.Http
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
#elif NET46
var handler = new HttpClientHandler
{
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
#else
var handler = new WebRequestHandler
{
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true,
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
};
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
#endif
if (!string.IsNullOrEmpty(clientX509Certificate2ThumbprintOrSubjectName))
@@ -63,13 +71,6 @@ namespace WireMock.Http
var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url);
WireMockList<string> contentTypeHeader = null;
bool contentTypeHeaderPresent = requestMessage.Headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase));
if (contentTypeHeaderPresent)
{
contentTypeHeader = requestMessage.Headers[HttpKnownHeaderNames.ContentType];
}
// Set Body if present
if (requestMessage.BodyAsBytes != null)
{
@@ -111,6 +112,12 @@ namespace WireMock.Http
if (httpResponseMessage.Content != null)
{
var stream = await httpResponseMessage.Content.ReadAsStreamAsync();
IEnumerable<string> contentTypeHeader = null;
if (headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)))
{
contentTypeHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value;
}
var body = await BodyParser.Parse(stream, contentTypeHeader?.FirstOrDefault());
responseMessage.Body = body.BodyAsString;
responseMessage.BodyAsJson = body.BodyAsJson;

View File

@@ -0,0 +1,47 @@
using JetBrains.Annotations;
namespace WireMock.Logging
{
/// <summary>
/// IWireMockLogger interface
/// </summary>
[PublicAPI]
public interface IWireMockLogger
{
/// <summary>
/// Writes the message at the Debug level using the specified parameters.
/// </summary>
/// <param name="formatString">The format string.</param>
/// <param name="args">The arguments.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Debug([NotNull] string formatString, [NotNull] params object[] args);
/// <summary>
/// Writes the message at the Info level using the specified parameters.
/// </summary>
/// <param name="formatString">The format string.</param>
/// <param name="args">The arguments.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Info([NotNull] string formatString, [NotNull] params object[] args);
/// <summary>
/// Writes the message at the Warning level using the specified parameters.
/// </summary>
/// <param name="formatString">The format string.</param>
/// <param name="args">The arguments.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Warn([NotNull] string formatString, [NotNull] params object[] args);
/// <summary>
/// Writes the message at the Error level using the specified parameters.
/// </summary>
/// <param name="formatString">The format string.</param>
/// <param name="args">The arguments.</param>
[PublicAPI]
[StringFormatMethod("formatString")]
void Error([NotNull] string formatString, [NotNull] params object[] args);
}
}

View File

@@ -0,0 +1,42 @@
using System;
namespace WireMock.Logging
{
/// <summary>
/// WireMockConsoleLogger which logs to Console
/// </summary>
/// <seealso cref="IWireMockLogger" />
public class WireMockConsoleLogger : IWireMockLogger
{
/// <see cref="IWireMockLogger.Debug"/>
public void Debug(string formatString, params object[] args)
{
Console.WriteLine(Format("Debug", formatString, args));
}
/// <see cref="IWireMockLogger.Info"/>
public void Info(string formatString, params object[] args)
{
Console.WriteLine(Format("Info", formatString, args));
}
/// <see cref="IWireMockLogger.Warn"/>
public void Warn(string formatString, params object[] args)
{
Console.WriteLine(Format("Warn", formatString, args));
}
/// <see cref="IWireMockLogger.Error"/>
public void Error(string formatString, params object[] args)
{
Console.WriteLine(Format("Error", formatString, args));
}
private static string Format(string level, string formatString, params object[] args)
{
string message = string.Format(formatString, args);
return $"{DateTime.UtcNow} [{level}] : {message}";
}
}
}

View File

@@ -0,0 +1,29 @@
namespace WireMock.Logging
{
/// <summary>
/// WireMockNullLogger which does not log.
/// </summary>
/// <seealso cref="IWireMockLogger" />
public class WireMockNullLogger : IWireMockLogger
{
/// <see cref="IWireMockLogger.Debug"/>
public void Debug(string formatString, params object[] args)
{
}
/// <see cref="IWireMockLogger.Info"/>
public void Info(string formatString, params object[] args)
{
}
/// <see cref="IWireMockLogger.Warn"/>
public void Warn(string formatString, params object[] args)
{
}
/// <see cref="IWireMockLogger.Error"/>
public void Error(string formatString, params object[] args)
{
}
}
}

View File

@@ -2,6 +2,7 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.Matchers.Request;
using WireMock.ResponseProviders;
namespace WireMock
{

View File

@@ -7,8 +7,8 @@ namespace WireMock.Matchers
/// <summary>
/// ExactMatcher
/// </summary>
/// <seealso cref="IMatcher" />
public class ExactMatcher : IMatcher
/// <seealso cref="IStringMatcher" />
public class ExactMatcher : IStringMatcher
{
private readonly string[] _values;
@@ -18,34 +18,24 @@ namespace WireMock.Matchers
/// <param name="values">The values.</param>
public ExactMatcher([NotNull] params string[] values)
{
Check.NotNull(values, nameof(values));
Check.HasNoNulls(values, nameof(values));
_values = values;
}
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
public double IsMatch(string input)
{
return MatchScores.ToScore(_values.Select(value => value.Equals(input)));
}
/// <summary>
/// Gets the value.
/// </summary>
/// <returns>Patterns</returns>
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
{
return _values;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>Name</returns>
/// <inheritdoc cref="IMatcher.GetName"/>
public string GetName()
{
return "ExactMatcher";

View File

@@ -0,0 +1,46 @@
using System.Linq;
using JetBrains.Annotations;
namespace WireMock.Matchers
{
/// <summary>
/// ExactMatcher
/// </summary>
/// <seealso cref="IObjectMatcher" />
public class ExactObjectMatcher : IObjectMatcher
{
private readonly object _object;
private readonly byte[] _bytes;
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="value">The value.</param>
public ExactObjectMatcher([NotNull] object value)
{
_object = value;
}
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="value">The value.</param>
public ExactObjectMatcher([NotNull] byte[] value)
{
_bytes = value;
}
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
public double IsMatch(object input)
{
bool equals = _object != null ? Equals(_object, input) : _bytes.SequenceEqual((byte[])input);
return MatchScores.ToScore(equals);
}
/// <inheritdoc cref="IMatcher.GetName"/>
public string GetName()
{
return "ExactObjectMatcher";
}
}
}

View File

@@ -0,0 +1,13 @@
namespace WireMock.Matchers
{
/// <summary>
/// IIgnoreCaseMatcher
/// </summary>
public interface IIgnoreCaseMatcher : IMatcher
{
/// <summary>
/// Ignore the case.
/// </summary>
bool IgnoreCase { get; }
}
}

View File

@@ -5,19 +5,6 @@
/// </summary>
public interface IMatcher
{
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
double IsMatch(string input);
/// <summary>
/// Gets the patterns.
/// </summary>
/// <returns>Patterns</returns>
string[] GetPatterns();
/// <summary>
/// Gets the name.
/// </summary>

View File

@@ -0,0 +1,15 @@
namespace WireMock.Matchers
{
/// <summary>
/// IObjectMatcher
/// </summary>
public interface IObjectMatcher : IMatcher
{
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
double IsMatch(object input);
}
}

View File

@@ -0,0 +1,21 @@
namespace WireMock.Matchers
{
/// <summary>
/// IStringMatcher
/// </summary>
public interface IStringMatcher : IMatcher
{
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
double IsMatch(string input);
/// <summary>
/// Gets the patterns.
/// </summary>
/// <returns>Patterns</returns>
string[] GetPatterns();
}
}

View File

@@ -10,8 +10,9 @@ namespace WireMock.Matchers
/// JSONPathMatcher
/// </summary>
/// <seealso cref="IMatcher" />
public class JsonPathMatcher : IMatcher
public class JsonPathMatcher : IStringMatcher, IObjectMatcher
{
// private readonly object _jsonPattern;
private readonly string[] _patterns;
/// <summary>
@@ -25,15 +26,20 @@ namespace WireMock.Matchers
_patterns = patterns;
}
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input string</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
//public JsonPathMatcher([NotNull] object jsonPattern)
//{
// Check.NotNull(jsonPattern, nameof(jsonPattern));
// _jsonPattern = jsonPattern;
//}
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
public double IsMatch(string input)
{
if (input == null)
{
return MatchScores.Mismatch;
}
try
{
@@ -47,19 +53,33 @@ namespace WireMock.Matchers
}
}
/// <summary>
/// Gets the patterns.
/// </summary>
/// <returns>Pattern</returns>
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
public double IsMatch(object input)
{
if (input == null)
{
return MatchScores.Mismatch;
}
try
{
var o = input as JObject ?? JObject.FromObject(input);
return MatchScores.ToScore(_patterns.Select(p => o.SelectToken(p) != null));
}
catch (Exception)
{
return MatchScores.Mismatch;
}
}
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
{
return _patterns;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>Name</returns>
/// <inheritdoc cref="IMatcher.GetName"/>
public string GetName()
{
return "JsonPathMatcher";

View File

@@ -9,8 +9,8 @@ namespace WireMock.Matchers
/// <summary>
/// Regular Expression Matcher
/// </summary>
/// <seealso cref="IMatcher" />
public class RegexMatcher : IMatcher
/// <seealso cref="IStringMatcher" />
public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
{
private readonly string[] _patterns;
private readonly Regex[] _expressions;
@@ -34,23 +34,24 @@ namespace WireMock.Matchers
Check.NotNull(patterns, nameof(patterns));
_patterns = patterns;
IgnoreCase = ignoreCase;
RegexOptions options = RegexOptions.Compiled;
if (ignoreCase)
{
options |= RegexOptions.IgnoreCase;
}
_expressions = patterns.Select(p => new Regex(p, options)).ToArray();
}
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input string</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
public double IsMatch(string input)
{
if (input == null)
{
return MatchScores.Mismatch;
}
try
{
@@ -62,24 +63,19 @@ namespace WireMock.Matchers
}
}
/// <summary>
/// Gets the patterns.
/// </summary>
/// <returns>Pattern</returns>
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public virtual string[] GetPatterns()
{
return _patterns;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>
/// Name
/// </returns>
/// <inheritdoc cref="IMatcher.GetName"/>
public virtual string GetName()
{
return "RegexMatcher";
}
/// <inheritdoc cref="IIgnoreCaseMatcher.IgnoreCase"/>
public bool IgnoreCase { get; }
}
}

View File

@@ -9,21 +9,21 @@ namespace WireMock.Matchers.Request
/// </summary>
public class RequestMessageBodyMatcher : IRequestMatcher
{
/// <summary>
/// The body as byte[].
/// </summary>
private readonly byte[] _bodyData;
/// <summary>
/// The body function
/// </summary>
public Func<string, bool> Func { get; }
/// <summary>
/// The body data function
/// The body data function for byte[]
/// </summary>
public Func<byte[], bool> DataFunc { get; }
/// <summary>
/// The body data function for json
/// </summary>
public Func<object, bool> JsonFunc { get; }
/// <summary>
/// The matcher.
/// </summary>
@@ -32,9 +32,7 @@ namespace WireMock.Matchers.Request
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary>
/// <param name="body">
/// The body Regex pattern.
/// </param>
/// <param name="body">The body.</param>
public RequestMessageBodyMatcher([NotNull] string body) : this(new SimMetricsMatcher(body))
{
}
@@ -42,21 +40,23 @@ namespace WireMock.Matchers.Request
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary>
/// <param name="body">
/// The body Regex pattern.
/// </param>
public RequestMessageBodyMatcher([NotNull] byte[] body)
/// <param name="body">The body.</param>
public RequestMessageBodyMatcher([NotNull] byte[] body) : this(new ExactObjectMatcher(body))
{
Check.NotNull(body, nameof(body));
_bodyData = body;
}
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary>
/// <param name="func">
/// The body func.
/// </param>
/// <param name="body">The body.</param>
public RequestMessageBodyMatcher([NotNull] object body) : this(new ExactObjectMatcher(body))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary>
/// <param name="func">The function.</param>
public RequestMessageBodyMatcher([NotNull] Func<string, bool> func)
{
Check.NotNull(func, nameof(func));
@@ -66,9 +66,7 @@ namespace WireMock.Matchers.Request
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary>
/// <param name="func">
/// The body func.
/// </param>
/// <param name="func">The function.</param>
public RequestMessageBodyMatcher([NotNull] Func<byte[], bool> func)
{
Check.NotNull(func, nameof(func));
@@ -78,23 +76,24 @@ namespace WireMock.Matchers.Request
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary>
/// <param name="matcher">
/// The body matcher.
/// </param>
/// <param name="func">The function.</param>
public RequestMessageBodyMatcher([NotNull] Func<object, bool> func)
{
Check.NotNull(func, nameof(func));
JsonFunc = func;
}
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
/// </summary>
/// <param name="matcher">The matcher.</param>
public RequestMessageBodyMatcher([NotNull] IMatcher matcher)
{
Check.NotNull(matcher, nameof(matcher));
Matcher = matcher;
}
/// <summary>
/// Determines whether the specified RequestMessage is match.
/// </summary>
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
/// <see cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
double score = IsMatch(requestMessage);
@@ -103,17 +102,41 @@ namespace WireMock.Matchers.Request
private double IsMatch(RequestMessage requestMessage)
{
if (Matcher != null)
return Matcher.IsMatch(requestMessage.Body);
if (requestMessage.Body != null)
{
if (Matcher is IStringMatcher stringMatcher)
{
return stringMatcher.IsMatch(requestMessage.Body);
}
}
if (_bodyData != null)
return MatchScores.ToScore(requestMessage.BodyAsBytes == _bodyData);
if (Matcher is IObjectMatcher objectMatcher)
{
if (requestMessage.BodyAsJson != null)
{
return objectMatcher.IsMatch(requestMessage.BodyAsJson);
}
if (requestMessage.BodyAsBytes != null)
{
return objectMatcher.IsMatch(requestMessage.BodyAsBytes);
}
}
if (Func != null)
{
return MatchScores.ToScore(requestMessage.Body != null && Func(requestMessage.Body));
}
if (DataFunc != null && requestMessage.BodyAsBytes != null)
if (DataFunc != null)
{
return MatchScores.ToScore(requestMessage.BodyAsBytes != null && DataFunc(requestMessage.BodyAsBytes));
}
if (JsonFunc != null)
{
return MatchScores.ToScore(requestMessage.BodyAsJson != null && JsonFunc(requestMessage.BodyAsJson));
}
return MatchScores.Mismatch;
}

View File

@@ -14,7 +14,7 @@ namespace WireMock.Matchers.Request
/// <summary>
/// The matchers.
/// </summary>
public IReadOnlyList<IMatcher> Matchers { get; }
public IReadOnlyList<IStringMatcher> Matchers { get; }
/// <summary>
/// The ClientIP functions.
@@ -25,7 +25,7 @@ namespace WireMock.Matchers.Request
/// Initializes a new instance of the <see cref="RequestMessageClientIPMatcher"/> class.
/// </summary>
/// <param name="clientIPs">The clientIPs.</param>
public RequestMessageClientIPMatcher([NotNull] params string[] clientIPs) : this(clientIPs.Select(ip => new WildcardMatcher(ip)).Cast<IMatcher>().ToArray())
public RequestMessageClientIPMatcher([NotNull] params string[] clientIPs) : this(clientIPs.Select(ip => new WildcardMatcher(ip)).Cast<IStringMatcher>().ToArray())
{
}
@@ -33,7 +33,7 @@ namespace WireMock.Matchers.Request
/// Initializes a new instance of the <see cref="RequestMessageClientIPMatcher"/> class.
/// </summary>
/// <param name="matchers">The matchers.</param>
public RequestMessageClientIPMatcher([NotNull] params IMatcher[] matchers)
public RequestMessageClientIPMatcher([NotNull] params IStringMatcher[] matchers)
{
Check.NotNull(matchers, nameof(matchers));
Matchers = matchers;
@@ -59,10 +59,14 @@ namespace WireMock.Matchers.Request
private double IsMatch(RequestMessage requestMessage)
{
if (Matchers != null)
{
return Matchers.Max(matcher => matcher.IsMatch(requestMessage.ClientIP));
}
if (Funcs != null)
{
return MatchScores.ToScore(requestMessage.ClientIP != null && Funcs.Any(func => func(requestMessage.ClientIP)));
}
return MatchScores.Mismatch;
}

View File

@@ -33,14 +33,7 @@ namespace WireMock.Matchers.Request
RequestMatchers = requestMatchers;
}
/// <summary>
/// Determines whether the specified RequestMessage is match.
/// </summary>
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
if (!RequestMatchers.Any())

View File

@@ -24,7 +24,7 @@ namespace WireMock.Matchers.Request
/// <value>
/// The matchers.
/// </value>
public IMatcher[] Matchers { get; }
public IStringMatcher[] Matchers { get; }
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
@@ -38,7 +38,7 @@ namespace WireMock.Matchers.Request
Check.NotNull(pattern, nameof(pattern));
Name = name;
Matchers = new IMatcher[] { new WildcardMatcher(pattern, ignoreCase) };
Matchers = new IStringMatcher[] { new WildcardMatcher(pattern, ignoreCase) };
}
/// <summary>
@@ -46,7 +46,7 @@ namespace WireMock.Matchers.Request
/// </summary>
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
public RequestMessageCookieMatcher([NotNull] string name, [NotNull] params IMatcher[] matchers)
public RequestMessageCookieMatcher([NotNull] string name, [NotNull] params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNull(matchers, nameof(matchers));
@@ -66,14 +66,7 @@ namespace WireMock.Matchers.Request
Funcs = funcs;
}
/// <summary>
/// Determines whether the specified RequestMessage is match.
/// </summary>
/// <param name="requestMessage">The RequestMessage.</param>
/// <param name="requestMatchResult">The RequestMatchResult.</param>
/// <returns>
/// A value between 0.0 - 1.0 of the similarity.
/// </returns>
/// <inheritdoc cref="IRequestMatcher.GetMatchingScore"/>
public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{
double score = IsMatch(requestMessage);
@@ -83,16 +76,24 @@ namespace WireMock.Matchers.Request
private double IsMatch(RequestMessage requestMessage)
{
if (requestMessage.Cookies == null)
{
return MatchScores.Mismatch;
}
if (Funcs != null)
{
return MatchScores.ToScore(Funcs.Any(f => f(requestMessage.Cookies)));
}
if (Matchers == null)
{
return MatchScores.Mismatch;
}
if (!requestMessage.Cookies.ContainsKey(Name))
{
return MatchScores.Mismatch;
}
string value = requestMessage.Cookies[Name];
return Matchers.Max(m => m.IsMatch(value));

View File

@@ -26,7 +26,7 @@ namespace WireMock.Matchers.Request
/// <value>
/// The matchers.
/// </value>
public IMatcher[] Matchers { get; }
public IStringMatcher[] Matchers { get; }
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageHeaderMatcher"/> class.
@@ -40,7 +40,7 @@ namespace WireMock.Matchers.Request
Check.NotNull(pattern, nameof(pattern));
Name = name;
Matchers = new IMatcher[] { new WildcardMatcher(pattern, ignoreCase) };
Matchers = new IStringMatcher[] { new WildcardMatcher(pattern, ignoreCase) };
}
/// <summary>
@@ -55,7 +55,7 @@ namespace WireMock.Matchers.Request
Check.NotNull(patterns, nameof(patterns));
Name = name;
Matchers = patterns.Select(pattern => new WildcardMatcher(pattern, ignoreCase)).Cast<IMatcher>().ToArray();
Matchers = patterns.Select(pattern => new WildcardMatcher(pattern, ignoreCase)).Cast<IStringMatcher>().ToArray();
}
/// <summary>
@@ -63,7 +63,7 @@ namespace WireMock.Matchers.Request
/// </summary>
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
public RequestMessageHeaderMatcher([NotNull] string name, [NotNull] params IMatcher[] matchers)
public RequestMessageHeaderMatcher([NotNull] string name, [NotNull] params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNull(matchers, nameof(matchers));
@@ -93,16 +93,24 @@ namespace WireMock.Matchers.Request
private double IsMatch(RequestMessage requestMessage)
{
if (requestMessage.Headers == null)
{
return MatchScores.Mismatch;
}
if (Funcs != null)
{
return MatchScores.ToScore(Funcs.Any(f => f(requestMessage.Headers.ToDictionary(entry => entry.Key, entry => entry.Value.ToArray()))));
}
if (Matchers == null)
{
return MatchScores.Mismatch;
}
if (!requestMessage.Headers.ContainsKey(Name))
{
return MatchScores.Mismatch;
}
WireMockList<string> list = requestMessage.Headers[Name];
return Matchers.Max(m => list.Max(value => m.IsMatch(value))); // TODO : is this correct ?

View File

@@ -27,6 +27,14 @@ namespace WireMock.Matchers.Request
/// </summary>
public IEnumerable<string> Values { get; }
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageParamMatcher"/> class.
/// </summary>
/// <param name="key">The key.</param>
public RequestMessageParamMatcher([NotNull] string key) : this(key, null)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageParamMatcher"/> class.
/// </summary>
@@ -65,9 +73,21 @@ namespace WireMock.Matchers.Request
return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query)));
}
List<string> values = requestMessage.GetParameter(Key);
var values = requestMessage.GetParameter(Key);
if (values == null)
{
// Key is not present, just return Mismatch
return MatchScores.Mismatch;
}
return MatchScores.ToScore(values?.Intersect(Values).Count() == Values.Count());
if (values.Count == 0 && (Values == null || !Values.Any()))
{
// Key is present, but no values or null, just return Perfect
return MatchScores.Perfect;
}
var matches = Values.Select(v => values.Contains(v));
return MatchScores.ToScore(matches);
}
}
}

View File

@@ -14,7 +14,7 @@ namespace WireMock.Matchers.Request
/// <summary>
/// The matcher.
/// </summary>
public IReadOnlyList<IMatcher> Matchers { get; }
public IReadOnlyList<IStringMatcher> Matchers { get; }
/// <summary>
/// The path functions
@@ -25,7 +25,7 @@ namespace WireMock.Matchers.Request
/// Initializes a new instance of the <see cref="RequestMessagePathMatcher"/> class.
/// </summary>
/// <param name="paths">The paths.</param>
public RequestMessagePathMatcher([NotNull] params string[] paths) : this(paths.Select(path => new WildcardMatcher(path)).Cast<IMatcher>().ToArray())
public RequestMessagePathMatcher([NotNull] params string[] paths) : this(paths.Select(path => new WildcardMatcher(path)).Cast<IStringMatcher>().ToArray())
{
}
@@ -33,7 +33,7 @@ namespace WireMock.Matchers.Request
/// Initializes a new instance of the <see cref="RequestMessagePathMatcher"/> class.
/// </summary>
/// <param name="matchers">The matchers.</param>
public RequestMessagePathMatcher([NotNull] params IMatcher[] matchers)
public RequestMessagePathMatcher([NotNull] params IStringMatcher[] matchers)
{
Check.NotNull(matchers, nameof(matchers));
Matchers = matchers;
@@ -59,10 +59,14 @@ namespace WireMock.Matchers.Request
private double IsMatch(RequestMessage requestMessage)
{
if (Matchers != null)
{
return Matchers.Max(m => m.IsMatch(requestMessage.Path));
}
if (Funcs != null)
{
return MatchScores.ToScore(requestMessage.Path != null && Funcs.Any(func => func(requestMessage.Path)));
}
return MatchScores.Mismatch;
}

View File

@@ -14,7 +14,7 @@ namespace WireMock.Matchers.Request
/// <summary>
/// The matchers.
/// </summary>
public IReadOnlyList<IMatcher> Matchers { get; }
public IReadOnlyList<IStringMatcher> Matchers { get; }
/// <summary>
/// The url functions.
@@ -25,7 +25,7 @@ namespace WireMock.Matchers.Request
/// Initializes a new instance of the <see cref="RequestMessageUrlMatcher"/> class.
/// </summary>
/// <param name="urls">The urls.</param>
public RequestMessageUrlMatcher([NotNull] params string[] urls) : this(urls.Select(url => new WildcardMatcher(url)).Cast<IMatcher>().ToArray())
public RequestMessageUrlMatcher([NotNull] params string[] urls) : this(urls.Select(url => new WildcardMatcher(url)).Cast<IStringMatcher>().ToArray())
{
}
@@ -33,7 +33,7 @@ namespace WireMock.Matchers.Request
/// Initializes a new instance of the <see cref="RequestMessageUrlMatcher"/> class.
/// </summary>
/// <param name="matchers">The matchers.</param>
public RequestMessageUrlMatcher([NotNull] params IMatcher[] matchers)
public RequestMessageUrlMatcher([NotNull] params IStringMatcher[] matchers)
{
Check.NotNull(matchers, nameof(matchers));
Matchers = matchers;
@@ -59,10 +59,14 @@ namespace WireMock.Matchers.Request
private double IsMatch(RequestMessage requestMessage)
{
if (Matchers != null)
{
return Matchers.Max(matcher => matcher.IsMatch(requestMessage.Url));
}
if (Funcs != null)
{
return MatchScores.ToScore(requestMessage.Url != null && Funcs.Any(func => func(requestMessage.Url)));
}
return MatchScores.Mismatch;
}

View File

@@ -10,8 +10,8 @@ namespace WireMock.Matchers
/// <summary>
/// SimMetricsMatcher
/// </summary>
/// <seealso cref="IMatcher" />
public class SimMetricsMatcher : IMatcher
/// <seealso cref="IStringMatcher" />
public class SimMetricsMatcher : IStringMatcher
{
private readonly string[] _patterns;
private readonly SimMetricType _simMetricType;
@@ -38,11 +38,7 @@ namespace WireMock.Matchers
_simMetricType = simMetricType;
}
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input string</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
public double IsMatch(string input)
{
IStringMetric m = GetStringMetricType();
@@ -93,19 +89,13 @@ namespace WireMock.Matchers
}
}
/// <summary>
/// Gets the pattern.
/// </summary>
/// <returns>Pattern</returns>
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
{
return _patterns;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>Name</returns>
/// <inheritdoc cref="IMatcher.GetName"/>
public string GetName()
{
return $"SimMetricsMatcher.{_simMetricType}";

View File

@@ -7,7 +7,7 @@ namespace WireMock.Matchers
/// <summary>
/// WildcardMatcher
/// </summary>
/// <seealso cref="IMatcher" />
/// <seealso cref="RegexMatcher" />
public class WildcardMatcher : RegexMatcher
{
private readonly string[] _patterns;
@@ -31,21 +31,13 @@ namespace WireMock.Matchers
_patterns = patterns;
}
/// <summary>
/// Gets the pattern.
/// </summary>
/// <returns>Pattern</returns>
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public override string[] GetPatterns()
{
return _patterns;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>
/// Name
/// </returns>
/// <inheritdoc cref="IMatcher.GetName"/>
public override string GetName()
{
return "WildcardMatcher";

View File

@@ -12,8 +12,8 @@ namespace WireMock.Matchers
/// <summary>
/// XPath2Matcher
/// </summary>
/// <seealso cref="WireMock.Matchers.IMatcher" />
public class XPathMatcher : IMatcher
/// <seealso cref="IStringMatcher" />
public class XPathMatcher : IStringMatcher
{
private readonly string[] _patterns;
@@ -28,15 +28,13 @@ namespace WireMock.Matchers
_patterns = patterns;
}
/// <summary>
/// Determines whether the specified input is match.
/// </summary>
/// <param name="input">The input string</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
public double IsMatch(string input)
{
if (input == null)
{
return MatchScores.Mismatch;
}
try
{
@@ -53,19 +51,13 @@ namespace WireMock.Matchers
}
}
/// <summary>
/// Gets the patterns.
/// </summary>
/// <returns>Patterns</returns>
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
public string[] GetPatterns()
{
return _patterns;
}
/// <summary>
/// Gets the name.
/// </summary>
/// <returns>Name</returns>
/// <inheritdoc cref="IMatcher.GetName"/>
public string GetName()
{
return "XPathMatcher";

View File

@@ -2,7 +2,6 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Threading;
using System.Threading.Tasks;
using JetBrains.Annotations;
@@ -50,7 +49,7 @@ namespace WireMock.Owin
_host = new WebHostBuilder()
.Configure(appBuilder =>
{
appBuilder.UseMiddleware<GlobalExceptionMiddleware>();
appBuilder.UseMiddleware<GlobalExceptionMiddleware>(_options);
_options.PreWireMockMiddlewareInit?.Invoke(appBuilder);
@@ -70,13 +69,13 @@ namespace WireMock.Owin
foreach (string url in _urls.Where(u => u.StartsWith("http://", StringComparison.OrdinalIgnoreCase)))
{
PortUtil.TryExtractProtocolAndPort(url, out string host, out int port);
options.Listen(IPAddress.Loopback, port);
options.Listen(System.Net.IPAddress.Loopback, port);
}
foreach (string url in _urls.Where(u => u.StartsWith("https://", StringComparison.OrdinalIgnoreCase)))
{
PortUtil.TryExtractProtocolAndPort(url, out string host, out int port);
options.Listen(IPAddress.Loopback, port, listenOptions =>
options.Listen(System.Net.IPAddress.Loopback, port, listenOptions =>
{
listenOptions.UseHttps(PublicCertificateHelper.GetX509Certificate2());
});
@@ -88,20 +87,20 @@ namespace WireMock.Owin
#endif
.Build();
IsStarted = true;
#if NETSTANDARD1_3
Console.WriteLine("WireMock.Net server using netstandard1.3");
return Task.Run(() =>
{
_host.Run(_cts.Token);
IsStarted = true;
}, _cts.Token);
#else
System.Console.WriteLine("WireMock.Net server using netstandard2.0");
IsStarted = true;
return Task.Run(() =>
{
_host.Run();
IsStarted = true;
}, _cts.Token);
#endif
}

View File

@@ -1,6 +1,5 @@
using System;
using System.Threading.Tasks;
using log4net;
using Newtonsoft.Json;
#if !NETSTANDARD
using Microsoft.Owin;
@@ -16,13 +15,18 @@ namespace WireMock.Owin
internal class GlobalExceptionMiddleware
#endif
{
private static readonly ILog Log = LogManager.GetLogger(typeof(GlobalExceptionMiddleware));
private readonly WireMockMiddlewareOptions _options;
#if !NETSTANDARD
public GlobalExceptionMiddleware(OwinMiddleware next) : base(next) { }
public GlobalExceptionMiddleware(OwinMiddleware next, WireMockMiddlewareOptions options) : base(next)
{
_options = options;
}
#else
public GlobalExceptionMiddleware(RequestDelegate next)
public GlobalExceptionMiddleware(RequestDelegate next, WireMockMiddlewareOptions options)
{
Next = next;
_options = options;
}
#endif
@@ -44,7 +48,7 @@ namespace WireMock.Owin
}
catch (Exception ex)
{
Log.Error("HttpStatusCode set to 500", ex);
_options.Logger.Error("HttpStatusCode set to 500 {0}", ex);
await _responseMapper.MapAsync(new ResponseMessage { StatusCode = 500, Body = JsonConvert.SerializeObject(ex) }, ctx.Response);
}
}

View File

@@ -1,8 +1,8 @@
using System;
using System.Collections.Generic;
using System.IO;
// using System.IO;
using System.Linq;
using System.Text;
// using System.Text;
using System.Threading.Tasks;
using WireMock.Util;
#if !NETSTANDARD

View File

@@ -57,11 +57,15 @@ namespace WireMock.Owin
private void StartServers()
{
#if NET46
Console.WriteLine("WireMock.Net server using .net 4.6.x or higher");
#else
Console.WriteLine("WireMock.Net server using .net 4.5.x or higher");
#endif
Action<IAppBuilder> startup = app =>
{
app.Use<GlobalExceptionMiddleware>();
app.Use<GlobalExceptionMiddleware>(_options);
_options.PreWireMockMiddlewareInit?.Invoke(app);
app.Use<WireMockMiddleware>(_options);
_options.PostWireMockMiddlewareInit?.Invoke(app);

View File

@@ -3,7 +3,6 @@ using System.Threading.Tasks;
using WireMock.Logging;
using WireMock.Matchers.Request;
using System.Linq;
using log4net;
using WireMock.Matchers;
using WireMock.Util;
using Newtonsoft.Json;
@@ -22,7 +21,6 @@ namespace WireMock.Owin
internal class WireMockMiddleware
#endif
{
private static readonly ILog Log = LogManager.GetLogger(typeof(WireMockMiddleware));
private static readonly Task CompletedTask = Task.FromResult(false);
private readonly WireMockMiddlewareOptions _options;
@@ -98,7 +96,7 @@ namespace WireMock.Owin
if (targetMapping == null)
{
logRequest = true;
Log.Warn("HttpStatusCode set to 404 : No matching mapping found");
_options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found");
response = new ResponseMessage { StatusCode = 404, Body = "No matching mapping found" };
return;
}
@@ -110,7 +108,7 @@ namespace WireMock.Owin
bool present = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out WireMockList<string> authorization);
if (!present || _options.AuthorizationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect)
{
Log.Error("HttpStatusCode set to 401");
_options.Logger.Error("HttpStatusCode set to 401");
response = new ResponseMessage { StatusCode = 401 };
return;
}
@@ -130,7 +128,7 @@ namespace WireMock.Owin
}
catch (Exception ex)
{
Log.Error("HttpStatusCode set to 500", ex);
_options.Logger.Error("HttpStatusCode set to 500");
response = new ResponseMessage { StatusCode = 500, Body = JsonConvert.SerializeObject(ex) };
}
finally

View File

@@ -15,13 +15,15 @@ namespace WireMock.Owin
{
internal class WireMockMiddlewareOptions
{
public IWireMockLogger Logger { get; set; }
public TimeSpan? RequestProcessingDelay { get; set; }
public IMatcher AuthorizationMatcher { get; set; }
public IStringMatcher AuthorizationMatcher { get; set; }
public bool AllowPartialMapping { get; set; }
public IDictionary<Guid, Mapping> Mappings { get; set; } = new ConcurrentDictionary<Guid, Mapping>();
public IDictionary<Guid, Mapping> Mappings { get; } = new ConcurrentDictionary<Guid, Mapping>();
public ObservableCollection<LogEntry> LogEntries { get; } = new ConcurentObservableCollection<LogEntry>();

View File

@@ -10,38 +10,52 @@ namespace WireMock.RequestBuilders
public interface IBodyRequestBuilder
{
/// <summary>
/// The with body.
/// WithBody: IMatcher
/// </summary>
/// <param name="matcher">The matcher.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody([NotNull] IMatcher matcher);
/// <summary>
/// The with body.
/// WithBody: Body as string
/// </summary>
/// <param name="body">The body.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(string body);
/// <summary>
/// The with body byte[].
/// WithBody: Body as byte[]
/// </summary>
/// <param name="body">The body as byte[].</param>
/// <param name="body">The body.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody(byte[] body);
/// <summary>
/// The with body string func.
/// WithBody: Body as object
/// </summary>
/// <param name="body">The body string function.</param>
/// <param name="body">The body.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody([NotNull] Func<string, bool> body);
IRequestBuilder WithBody(object body);
/// <summary>
/// The with body byte[] func.
///WithBody: func (string)
/// </summary>
/// <param name="body">The body byte[] function.</param>
/// <param name="func">The function.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody([NotNull] Func<byte[], bool> body);
IRequestBuilder WithBody([NotNull] Func<string, bool> func);
/// <summary>
///WithBody: func (byte[])
/// </summary>
/// <param name="func">The function.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody([NotNull] Func<byte[], bool> func);
/// <summary>
///WithBody: func (object)
/// </summary>
/// <param name="func">The function.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithBody([NotNull] Func<object, bool> func);
}
}

View File

@@ -14,7 +14,7 @@ namespace WireMock.RequestBuilders
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithClientIP([NotNull] params IMatcher[] matchers);
IRequestBuilder WithClientIP([NotNull] params IStringMatcher[] matchers);
/// <summary>
/// The with ClientIP.

View File

@@ -35,7 +35,7 @@ namespace WireMock.RequestBuilders
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithHeader([NotNull] string name, [NotNull] params IMatcher[] matchers);
IRequestBuilder WithHeader([NotNull] string name, [NotNull] params IStringMatcher[] matchers);
/// <summary>
/// The with header.
@@ -59,7 +59,7 @@ namespace WireMock.RequestBuilders
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithCookie([NotNull] string name, [NotNull] params IMatcher[] matchers);
IRequestBuilder WithCookie([NotNull] string name, [NotNull] params IStringMatcher[] matchers);
/// <summary>
/// The with cookie.

View File

@@ -6,12 +6,19 @@ using WireMock.Util;
namespace WireMock.RequestBuilders
{
/// <summary>
/// The ParametersRequestBuilder interface.
/// The ParamsRequestBuilder interface.
/// </summary>
public interface IParamsRequestBuilder
{
/// <summary>
/// The with parameters.
/// WithParam (key only)
/// </summary>
/// <param name="key">The key.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithParam([NotNull] string key);
/// <summary>
/// WithParam (values)
/// </summary>
/// <param name="key">The key.</param>
/// <param name="values">The values.</param>
@@ -19,7 +26,7 @@ namespace WireMock.RequestBuilders
IRequestBuilder WithParam([NotNull] string key, [CanBeNull] params string[] values);
/// <summary>
/// The with parameters.
/// WithParam (funcs)
/// </summary>
/// <param name="funcs">The funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>

View File

@@ -14,7 +14,7 @@ namespace WireMock.RequestBuilders
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithPath([NotNull] params IMatcher[] matchers);
IRequestBuilder WithPath([NotNull] params IStringMatcher[] matchers);
/// <summary>
/// The with path.
@@ -35,7 +35,7 @@ namespace WireMock.RequestBuilders
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
IRequestBuilder WithUrl([NotNull] params IMatcher[] matchers);
IRequestBuilder WithUrl([NotNull] params IStringMatcher[] matchers);
/// <summary>
/// The with url.

View File

@@ -59,7 +59,7 @@ namespace WireMock.RequestBuilders
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public IRequestBuilder WithClientIP(params IMatcher[] matchers)
public IRequestBuilder WithClientIP(params IStringMatcher[] matchers)
{
Check.NotNullOrEmpty(matchers, nameof(matchers));
@@ -98,7 +98,7 @@ namespace WireMock.RequestBuilders
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public IRequestBuilder WithPath(params IMatcher[] matchers)
public IRequestBuilder WithPath(params IStringMatcher[] matchers)
{
Check.NotNullOrEmpty(matchers, nameof(matchers));
@@ -137,7 +137,7 @@ namespace WireMock.RequestBuilders
/// </summary>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public IRequestBuilder WithUrl(params IMatcher[] matchers)
public IRequestBuilder WithUrl(params IStringMatcher[] matchers)
{
Check.NotNullOrEmpty(matchers, nameof(matchers));
@@ -234,67 +234,28 @@ namespace WireMock.RequestBuilders
return this;
}
/// <summary>
/// The with body.
/// </summary>
/// <param name="body">
/// The body.
/// </param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(string)"/>
public IRequestBuilder WithBody(string body)
{
_requestMatchers.Add(new RequestMessageBodyMatcher(body));
return this;
}
/// <summary>
/// The with body byte[].
/// </summary>
/// <param name="body">
/// The body as byte[].
/// </param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(byte[])"/>
public IRequestBuilder WithBody(byte[] body)
{
_requestMatchers.Add(new RequestMessageBodyMatcher(body));
return this;
}
/// <summary>
/// The with body.
/// </summary>
/// <param name="func">
/// The body function.
/// </param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public IRequestBuilder WithBody(Func<string, bool> func)
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(object)"/>
public IRequestBuilder WithBody(object body)
{
Check.NotNull(func, nameof(func));
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
_requestMatchers.Add(new RequestMessageBodyMatcher(body));
return this;
}
/// <summary>
/// The with body.
/// </summary>
/// <param name="func">
/// The body function.
/// </param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public IRequestBuilder WithBody(Func<byte[], bool> func)
{
Check.NotNull(func, nameof(func));
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
return this;
}
/// <summary>
/// The with body.
/// </summary>
/// <param name="matcher">The matcher.</param>
/// <returns>The <see cref="IRequestBuilder" />.</returns>
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(IMatcher)"/>
public IRequestBuilder WithBody(IMatcher matcher)
{
Check.NotNull(matcher, nameof(matcher));
@@ -303,16 +264,43 @@ namespace WireMock.RequestBuilders
return this;
}
/// <summary>
/// The with parameters.
/// </summary>
/// <param name="key">
/// The key.
/// </param>
/// <param name="values">
/// The values.
/// </param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(Func{string, bool})"/>
public IRequestBuilder WithBody(Func<string, bool> func)
{
Check.NotNull(func, nameof(func));
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
return this;
}
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(Func{byte[], bool})"/>
public IRequestBuilder WithBody(Func<byte[], bool> func)
{
Check.NotNull(func, nameof(func));
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
return this;
}
/// <inheritdoc cref="IBodyRequestBuilder.WithBody(Func{object, bool})"/>
public IRequestBuilder WithBody(Func<object, bool> func)
{
Check.NotNull(func, nameof(func));
_requestMatchers.Add(new RequestMessageBodyMatcher(func));
return this;
}
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string)"/>
public IRequestBuilder WithParam(string key)
{
Check.NotNull(key, nameof(key));
_requestMatchers.Add(new RequestMessageParamMatcher(key));
return this;
}
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(string, string[])"/>
public IRequestBuilder WithParam(string key, params string[] values)
{
Check.NotNull(key, nameof(key));
@@ -321,11 +309,7 @@ namespace WireMock.RequestBuilders
return this;
}
/// <summary>
/// The with parameters.
/// </summary>
/// <param name="funcs">The funcs.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
/// <inheritdoc cref="IParamsRequestBuilder.WithParam(Func{IDictionary{string, WireMockList{string}}, bool}[])"/>
public IRequestBuilder WithParam(params Func<IDictionary<string, WireMockList<string>>, bool>[] funcs)
{
Check.NotNullOrEmpty(funcs, nameof(funcs));
@@ -360,7 +344,7 @@ namespace WireMock.RequestBuilders
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public IRequestBuilder WithHeader(string name, params IMatcher[] matchers)
public IRequestBuilder WithHeader(string name, params IStringMatcher[] matchers)
{
Check.NotNull(name, nameof(name));
Check.NotNullOrEmpty(matchers, nameof(matchers));
@@ -401,7 +385,7 @@ namespace WireMock.RequestBuilders
/// <param name="name">The name.</param>
/// <param name="matchers">The matchers.</param>
/// <returns>The <see cref="IRequestBuilder"/>.</returns>
public IRequestBuilder WithCookie(string name, params IMatcher[] matchers)
public IRequestBuilder WithCookie(string name, params IStringMatcher[] matchers)
{
Check.NotNullOrEmpty(matchers, nameof(matchers));

View File

@@ -180,10 +180,11 @@ namespace WireMock
queryString = queryString.Substring(1);
}
return queryString.Split('&').Aggregate(new Dictionary<string, WireMockList<string>>(),
return queryString.Split(new[] { '&' }, StringSplitOptions.RemoveEmptyEntries)
.Aggregate(new Dictionary<string, WireMockList<string>>(),
(dict, term) =>
{
var parts = term.Split('=');
string[] parts = term.Split(new[] { '=' }, StringSplitOptions.RemoveEmptyEntries);
string key = parts[0];
if (!dict.ContainsKey(key))
{
@@ -192,7 +193,8 @@ namespace WireMock
if (parts.Length == 2)
{
dict[key].Add(parts[1]);
string[] values = parts[1].Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);
dict[key].AddRange(values);
}
return dict;
@@ -204,7 +206,7 @@ namespace WireMock
/// </summary>
/// <param name="key">The key.</param>
/// <returns>The query parameter.</returns>
public List<string> GetParameter(string key)
public WireMockList<string> GetParameter(string key)
{
if (Query == null)
{

View File

@@ -19,5 +19,10 @@
/// Convert to bytes
/// </summary>
public const string Bytes = "Bytes";
/// <summary>
/// Convert to Json object
/// </summary>
public const string Json = "Json";
}
}

View File

@@ -18,6 +18,17 @@ namespace WireMock.ResponseBuilders
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithBody([NotNull] string body, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null);
/// <summary>
/// WithBody : Create a ... response based on a callback function.
/// </summary>
/// <param name="bodyFactory">The delegate to build the body.</param>
/// <param name="destination">The Body Destination format (SameAsSource, String or Bytes).</param>
/// <param name="encoding">The body encoding.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithBody([NotNull] Func<RequestMessage,string> bodyFactory, [CanBeNull] string destination = BodyDestinationFormat.SameAsSource, [CanBeNull] Encoding encoding = null);
/// <summary>
/// WithBody : Create a ... response based on a bytearray.
/// </summary>

View File

@@ -0,0 +1,19 @@
using System;
using JetBrains.Annotations;
using WireMock.ResponseProviders;
namespace WireMock.ResponseBuilders
{
/// <summary>
/// The CallbackResponseBuilder interface.
/// </summary>
public interface ICallbackResponseBuilder : IResponseProvider
{
/// <summary>
/// The callback builder
/// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, ResponseMessage> callbackHandler);
}
}

View File

@@ -5,7 +5,7 @@ namespace WireMock.ResponseBuilders
/// <summary>
/// The DelayResponseBuilder interface.
/// </summary>
public interface IDelayResponseBuilder : IResponseProvider
public interface IDelayResponseBuilder : ICallbackResponseBuilder
{
/// <summary>
/// The with delay.

View File

@@ -1,343 +1,374 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.Http;
using WireMock.Settings;
using WireMock.Transformers;
using WireMock.Util;
using WireMock.Validation;
namespace WireMock.ResponseBuilders
{
/// <summary>
/// The Response.
/// </summary>
public class Response : IResponseBuilder
{
private HttpClient _httpClientForProxy;
/// <summary>
/// The delay
/// </summary>
public TimeSpan? Delay { get; private set; }
/// <summary>
/// Gets a value indicating whether [use transformer].
/// </summary>
/// <value>
/// <c>true</c> if [use transformer]; otherwise, <c>false</c>.
/// </value>
public bool UseTransformer { get; private set; }
/// <summary>
/// The Proxy URL to use.
/// </summary>
public string ProxyUrl { get; private set; }
/// <summary>
/// The client X509Certificate2 Thumbprint or SubjectName to use.
/// </summary>
public string ClientX509Certificate2ThumbprintOrSubjectName { get; private set; }
/// <summary>
/// Gets the response message.
/// </summary>
/// <value>
/// The response message.
/// </value>
public ResponseMessage ResponseMessage { get; }
/// <summary>
/// Creates this instance.
/// </summary>
/// <param name="responseMessage">ResponseMessage</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public static IResponseBuilder Create([CanBeNull] ResponseMessage responseMessage = null)
{
var message = responseMessage ?? new ResponseMessage { StatusCode = (int)HttpStatusCode.OK };
return new Response(message);
}
/// <summary>
/// Creates this instance.
/// </summary>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public static IResponseBuilder Create([NotNull] Func<ResponseMessage> func)
{
Check.NotNull(func, nameof(func));
return new Response(func());
}
/// <summary>
/// Initializes a new instance of the <see cref="Response"/> class.
/// </summary>
/// <param name="responseMessage">
/// The response.
/// </param>
private Response(ResponseMessage responseMessage)
{
ResponseMessage = responseMessage;
}
/// <summary>
/// The with status code.
/// </summary>
/// <param name="code">The code.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>\
[PublicAPI]
public IResponseBuilder WithStatusCode(int code)
{
ResponseMessage.StatusCode = code;
return this;
}
/// <summary>
/// The with status code.
/// </summary>
/// <param name="code">The code.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public IResponseBuilder WithStatusCode(HttpStatusCode code)
{
return WithStatusCode((int)code);
}
/// <summary>
/// The with Success status code (200).
/// </summary>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public IResponseBuilder WithSuccess()
{
return WithStatusCode((int)HttpStatusCode.OK);
}
/// <summary>
/// The with NotFound status code (404).
/// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public IResponseBuilder WithNotFound()
{
return WithStatusCode((int)HttpStatusCode.NotFound);
}
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeader(string, string[])"/>
public IResponseBuilder WithHeader(string name, params string[] values)
{
Check.NotNull(name, nameof(name));
ResponseMessage.AddHeader(name, values);
return this;
}
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string})"/>
public IResponseBuilder WithHeaders(IDictionary<string, string> headers)
{
Check.NotNull(headers, nameof(headers));
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
return this;
}
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string[]})"/>
public IResponseBuilder WithHeaders(IDictionary<string, string[]> headers)
{
Check.NotNull(headers, nameof(headers));
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
return this;
}
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, WireMockList{string}})"/>
public IResponseBuilder WithHeaders(IDictionary<string, WireMockList<string>> headers)
{
ResponseMessage.Headers = headers;
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(byte[], string, Encoding)"/>
public IResponseBuilder WithBody(byte[] body, string destination, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));
ResponseMessage.BodyDestination = destination;
switch (destination)
{
case BodyDestinationFormat.String:
var enc = encoding ?? Encoding.UTF8;
ResponseMessage.BodyAsBytes = null;
ResponseMessage.Body = enc.GetString(body);
ResponseMessage.BodyEncoding = enc;
break;
default:
ResponseMessage.BodyAsBytes = body;
ResponseMessage.BodyEncoding = null;
break;
}
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromFile"/>
public IResponseBuilder WithBodyFromFile(string filename, bool cache = true)
{
Check.NotNull(filename, nameof(filename));
ResponseMessage.BodyEncoding = null;
ResponseMessage.BodyAsFileIsCached = cache;
if (cache)
{
ResponseMessage.Body = null;
ResponseMessage.BodyAsBytes = File.ReadAllBytes(filename);
ResponseMessage.BodyAsFile = null;
}
else
{
ResponseMessage.Body = null;
ResponseMessage.BodyAsBytes = null;
ResponseMessage.BodyAsFile = filename;
}
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(string, string, Encoding)"/>
public IResponseBuilder WithBody(string body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));
encoding = encoding ?? Encoding.UTF8;
ResponseMessage.BodyDestination = destination;
switch (destination)
{
case BodyDestinationFormat.Bytes:
ResponseMessage.Body = null;
ResponseMessage.BodyAsBytes = encoding.GetBytes(body);
ResponseMessage.BodyEncoding = encoding;
break;
default:
ResponseMessage.Body = body;
ResponseMessage.BodyAsBytes = null;
ResponseMessage.BodyEncoding = encoding;
break;
}
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyAsJson"/>
public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));
ResponseMessage.BodyDestination = null;
ResponseMessage.BodyAsJson = body;
ResponseMessage.BodyEncoding = encoding;
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromBase64"/>
public IResponseBuilder WithBodyFromBase64(string bodyAsbase64, Encoding encoding = null)
{
Check.NotNull(bodyAsbase64, nameof(bodyAsbase64));
encoding = encoding ?? Encoding.UTF8;
ResponseMessage.BodyDestination = null;
ResponseMessage.Body = encoding.GetString(Convert.FromBase64String(bodyAsbase64));
ResponseMessage.BodyEncoding = encoding;
return this;
}
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer"/>
public IResponseBuilder WithTransformer()
{
UseTransformer = true;
return this;
}
/// <inheritdoc cref="IDelayResponseBuilder.WithDelay(TimeSpan)"/>
public IResponseBuilder WithDelay(TimeSpan delay)
{
Check.Condition(delay, d => d > TimeSpan.Zero, nameof(delay));
Delay = delay;
return this;
}
/// <inheritdoc cref="IDelayResponseBuilder.WithDelay(int)"/>
public IResponseBuilder WithDelay(int milliseconds)
{
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
}
/// <inheritdoc cref="IProxyResponseBuilder.WithProxy(string, string)"/>
public IResponseBuilder WithProxy(string proxyUrl, string clientX509Certificate2ThumbprintOrSubjectName = null)
{
Check.NotNullOrEmpty(proxyUrl, nameof(proxyUrl));
ProxyUrl = proxyUrl;
ClientX509Certificate2ThumbprintOrSubjectName = clientX509Certificate2ThumbprintOrSubjectName;
_httpClientForProxy = HttpClientHelper.CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName);
return this;
}
/// <inheritdoc cref="IProxyResponseBuilder.WithProxy(IProxyAndRecordSettings)"/>
public IResponseBuilder WithProxy(IProxyAndRecordSettings settings)
{
Check.NotNull(settings, nameof(settings));
return WithProxy(settings.Url, settings.ClientX509Certificate2ThumbprintOrSubjectName);
}
/// <summary>
/// The provide response.
/// </summary>
/// <param name="requestMessage">The request.</param>
/// <returns>The <see cref="ResponseMessage"/>.</returns>
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
{
Check.NotNull(requestMessage, nameof(requestMessage));
if (Delay != null)
{
await Task.Delay(Delay.Value);
}
if (ProxyUrl != null && _httpClientForProxy != null)
{
var requestUri = new Uri(requestMessage.Url);
var proxyUri = new Uri(ProxyUrl);
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
return await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri);
}
if (UseTransformer)
{
return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage);
}
return ResponseMessage;
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.Http;
using WireMock.Settings;
using WireMock.Transformers;
using WireMock.Util;
using WireMock.Validation;
namespace WireMock.ResponseBuilders
{
/// <summary>
/// The Response.
/// </summary>
public class Response : IResponseBuilder
{
private HttpClient _httpClientForProxy;
/// <summary>
/// The delay
/// </summary>
public TimeSpan? Delay { get; private set; }
/// <summary>
/// Gets a value indicating whether [use transformer].
/// </summary>
/// <value>
/// <c>true</c> if [use transformer]; otherwise, <c>false</c>.
/// </value>
public bool UseTransformer { get; private set; }
/// <summary>
/// The Proxy URL to use.
/// </summary>
public string ProxyUrl { get; private set; }
/// <summary>
/// The client X509Certificate2 Thumbprint or SubjectName to use.
/// </summary>
public string ClientX509Certificate2ThumbprintOrSubjectName { get; private set; }
/// <summary>
/// Gets the response message.
/// </summary>
public ResponseMessage ResponseMessage { get; }
/// <summary>
/// A delegate to execute to generate the response
/// </summary>
public Func<RequestMessage, ResponseMessage> Callback { get; private set; }
/// <summary>
/// Creates this instance.
/// </summary>
/// <param name="responseMessage">ResponseMessage</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public static IResponseBuilder Create([CanBeNull] ResponseMessage responseMessage = null)
{
var message = responseMessage ?? new ResponseMessage { StatusCode = (int)HttpStatusCode.OK };
return new Response(message);
}
/// <summary>
/// Creates this instance with the specified function.
/// </summary>
/// <param name="func">The callback function.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public static IResponseBuilder Create([NotNull] Func<ResponseMessage> func)
{
Check.NotNull(func, nameof(func));
return new Response(func());
}
/// <summary>
/// Initializes a new instance of the <see cref="Response"/> class.
/// </summary>
/// <param name="responseMessage">
/// The response.
/// </param>
private Response(ResponseMessage responseMessage)
{
ResponseMessage = responseMessage;
}
/// <summary>
/// The with status code.
/// </summary>
/// <param name="code">The code.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>\
[PublicAPI]
public IResponseBuilder WithStatusCode(int code)
{
ResponseMessage.StatusCode = code;
return this;
}
/// <summary>
/// The with status code.
/// </summary>
/// <param name="code">The code.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public IResponseBuilder WithStatusCode(HttpStatusCode code)
{
return WithStatusCode((int)code);
}
/// <summary>
/// The with Success status code (200).
/// </summary>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public IResponseBuilder WithSuccess()
{
return WithStatusCode((int)HttpStatusCode.OK);
}
/// <summary>
/// The with NotFound status code (404).
/// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI]
public IResponseBuilder WithNotFound()
{
return WithStatusCode((int)HttpStatusCode.NotFound);
}
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeader(string, string[])"/>
public IResponseBuilder WithHeader(string name, params string[] values)
{
Check.NotNull(name, nameof(name));
ResponseMessage.AddHeader(name, values);
return this;
}
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string})"/>
public IResponseBuilder WithHeaders(IDictionary<string, string> headers)
{
Check.NotNull(headers, nameof(headers));
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
return this;
}
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string[]})"/>
public IResponseBuilder WithHeaders(IDictionary<string, string[]> headers)
{
Check.NotNull(headers, nameof(headers));
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
return this;
}
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, WireMockList{string}})"/>
public IResponseBuilder WithHeaders(IDictionary<string, WireMockList<string>> headers)
{
ResponseMessage.Headers = headers;
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(Func{RequestMessage, string}, string, Encoding)"/>
public IResponseBuilder WithBody(Func<RequestMessage, string> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
{
return WithCallback(req => new ResponseMessage { Body = bodyFactory(req) });
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(byte[], string, Encoding)"/>
public IResponseBuilder WithBody(byte[] body, string destination, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));
ResponseMessage.BodyDestination = destination;
switch (destination)
{
case BodyDestinationFormat.String:
var enc = encoding ?? Encoding.UTF8;
ResponseMessage.BodyAsBytes = null;
ResponseMessage.Body = enc.GetString(body);
ResponseMessage.BodyEncoding = enc;
break;
default:
ResponseMessage.BodyAsBytes = body;
ResponseMessage.BodyEncoding = null;
break;
}
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromFile"/>
public IResponseBuilder WithBodyFromFile(string filename, bool cache = true)
{
Check.NotNull(filename, nameof(filename));
ResponseMessage.BodyEncoding = null;
ResponseMessage.BodyAsFileIsCached = cache;
if (cache)
{
ResponseMessage.Body = null;
ResponseMessage.BodyAsBytes = File.ReadAllBytes(filename);
ResponseMessage.BodyAsFile = null;
}
else
{
ResponseMessage.Body = null;
ResponseMessage.BodyAsBytes = null;
ResponseMessage.BodyAsFile = filename;
}
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(string, string, Encoding)"/>
public IResponseBuilder WithBody(string body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));
encoding = encoding ?? Encoding.UTF8;
ResponseMessage.BodyDestination = destination;
ResponseMessage.BodyEncoding = encoding;
switch (destination)
{
case BodyDestinationFormat.Bytes:
ResponseMessage.Body = null;
ResponseMessage.BodyAsJson = null;
ResponseMessage.BodyAsBytes = encoding.GetBytes(body);
break;
case BodyDestinationFormat.Json:
ResponseMessage.Body = null;
ResponseMessage.BodyAsJson = JsonConvert.DeserializeObject(body);
ResponseMessage.BodyAsBytes = null;
break;
default:
ResponseMessage.Body = body;
ResponseMessage.BodyAsJson = null;
ResponseMessage.BodyAsBytes = null;
break;
}
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyAsJson"/>
public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null)
{
Check.NotNull(body, nameof(body));
ResponseMessage.BodyDestination = null;
ResponseMessage.BodyAsJson = body;
ResponseMessage.BodyEncoding = encoding;
return this;
}
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromBase64"/>
public IResponseBuilder WithBodyFromBase64(string bodyAsbase64, Encoding encoding = null)
{
Check.NotNull(bodyAsbase64, nameof(bodyAsbase64));
encoding = encoding ?? Encoding.UTF8;
ResponseMessage.BodyDestination = null;
ResponseMessage.Body = encoding.GetString(Convert.FromBase64String(bodyAsbase64));
ResponseMessage.BodyEncoding = encoding;
return this;
}
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer"/>
public IResponseBuilder WithTransformer()
{
UseTransformer = true;
return this;
}
/// <inheritdoc cref="IDelayResponseBuilder.WithDelay(TimeSpan)"/>
public IResponseBuilder WithDelay(TimeSpan delay)
{
Check.Condition(delay, d => d > TimeSpan.Zero, nameof(delay));
Delay = delay;
return this;
}
/// <inheritdoc cref="IDelayResponseBuilder.WithDelay(int)"/>
public IResponseBuilder WithDelay(int milliseconds)
{
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
}
/// <inheritdoc cref="IProxyResponseBuilder.WithProxy(string, string)"/>
public IResponseBuilder WithProxy(string proxyUrl, string clientX509Certificate2ThumbprintOrSubjectName = null)
{
Check.NotNullOrEmpty(proxyUrl, nameof(proxyUrl));
ProxyUrl = proxyUrl;
ClientX509Certificate2ThumbprintOrSubjectName = clientX509Certificate2ThumbprintOrSubjectName;
_httpClientForProxy = HttpClientHelper.CreateHttpClient(clientX509Certificate2ThumbprintOrSubjectName);
return this;
}
/// <inheritdoc cref="IProxyResponseBuilder.WithProxy(IProxyAndRecordSettings)"/>
public IResponseBuilder WithProxy(IProxyAndRecordSettings settings)
{
Check.NotNull(settings, nameof(settings));
return WithProxy(settings.Url, settings.ClientX509Certificate2ThumbprintOrSubjectName);
}
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback"/>
public IResponseBuilder WithCallback(Func<RequestMessage, ResponseMessage> callbackHandler)
{
Check.NotNull(callbackHandler, nameof(callbackHandler));
Callback = callbackHandler;
return this;
}
/// <summary>
/// The provide response.
/// </summary>
/// <param name="requestMessage">The request.</param>
/// <returns>The <see cref="ResponseMessage"/>.</returns>
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
{
Check.NotNull(requestMessage, nameof(requestMessage));
if (Delay != null)
{
await Task.Delay(Delay.Value);
}
if (ProxyUrl != null && _httpClientForProxy != null)
{
var requestUri = new Uri(requestMessage.Url);
var proxyUri = new Uri(ProxyUrl);
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
return await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri);
}
if (UseTransformer)
{
return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage);
}
if (Callback != null)
{
return Callback(requestMessage);
}
return ResponseMessage;
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.Validation;
namespace WireMock.ResponseProviders
{
internal class DynamicAsyncResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, Task<ResponseMessage>> _responseMessageFunc;
public DynamicAsyncResponseProvider([NotNull] Func<RequestMessage, Task<ResponseMessage>> responseMessageFunc)
{
Check.NotNull(responseMessageFunc, nameof(responseMessageFunc));
_responseMessageFunc = responseMessageFunc;
}
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
{
return _responseMessageFunc(requestMessage);
}
}
}

View File

@@ -0,0 +1,24 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.Validation;
namespace WireMock.ResponseProviders
{
internal class DynamicResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, ResponseMessage> _responseMessageFunc;
public DynamicResponseProvider([NotNull] Func<RequestMessage, ResponseMessage> responseMessageFunc)
{
Check.NotNull(responseMessageFunc, nameof(responseMessageFunc));
_responseMessageFunc = responseMessageFunc;
}
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
{
return Task.FromResult(_responseMessageFunc(requestMessage));
}
}
}

View File

@@ -1,7 +1,7 @@
using System.Threading.Tasks;
using JetBrains.Annotations;
namespace WireMock
namespace WireMock.ResponseProviders
{
/// <summary>
/// The Response Provider interface.

View File

@@ -0,0 +1,28 @@
using System;
using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.Settings;
using WireMock.Validation;
namespace WireMock.ResponseProviders
{
internal class ProxyAsyncResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, IProxyAndRecordSettings, Task<ResponseMessage>> _responseMessageFunc;
private readonly IProxyAndRecordSettings _settings;
public ProxyAsyncResponseProvider([NotNull] Func<RequestMessage, IProxyAndRecordSettings, Task<ResponseMessage>> responseMessageFunc, [NotNull] IProxyAndRecordSettings settings)
{
Check.NotNull(responseMessageFunc, nameof(responseMessageFunc));
Check.NotNull(settings, nameof(settings));
_responseMessageFunc = responseMessageFunc;
_settings = settings;
}
public Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage)
{
return _responseMessageFunc(requestMessage, _settings);
}
}
}

View File

@@ -2,9 +2,7 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using SimMetrics.Net;
using WireMock.Admin.Mappings;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
@@ -40,19 +38,19 @@ namespace WireMock.Serialization
{
ClientIP = clientIPMatchers != null && clientIPMatchers.Any() ? new ClientIPModel
{
Matchers = Map(clientIPMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)),
Matchers = MatcherMapper.Map(clientIPMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)),
Funcs = Map(clientIPMatchers.Where(m => m.Funcs != null).SelectMany(m => m.Funcs))
} : null,
Path = pathMatchers != null && pathMatchers.Any() ? new PathModel
{
Matchers = Map(pathMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)),
Matchers = MatcherMapper.Map(pathMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)),
Funcs = Map(pathMatchers.Where(m => m.Funcs != null).SelectMany(m => m.Funcs))
} : null,
Url = urlMatchers != null && urlMatchers.Any() ? new UrlModel
{
Matchers = Map(urlMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)),
Matchers = MatcherMapper.Map(urlMatchers.Where(m => m.Matchers != null).SelectMany(m => m.Matchers)),
Funcs = Map(urlMatchers.Where(m => m.Funcs != null).SelectMany(m => m.Funcs))
} : null,
@@ -61,14 +59,14 @@ namespace WireMock.Serialization
Headers = headerMatchers != null && headerMatchers.Any() ? headerMatchers.Select(hm => new HeaderModel
{
Name = hm.Name,
Matchers = Map(hm.Matchers),
Matchers = MatcherMapper.Map(hm.Matchers),
Funcs = Map(hm.Funcs)
}).ToList() : null,
Cookies = cookieMatchers != null && cookieMatchers.Any() ? cookieMatchers.Select(cm => new CookieModel
{
Name = cm.Name,
Matchers = Map(cm.Matchers),
Matchers = MatcherMapper.Map(cm.Matchers),
Funcs = Map(cm.Funcs)
}).ToList() : null,
@@ -81,7 +79,7 @@ namespace WireMock.Serialization
Body = methodMatcher?.Methods != null && methodMatcher.Methods.Any(m => m == "get") ? null : new BodyModel
{
Matcher = bodyMatcher != null ? Map(bodyMatcher.Matcher) : null,
Matcher = bodyMatcher != null ? MatcherMapper.Map(bodyMatcher.Matcher) : null,
Func = bodyMatcher != null ? Map(bodyMatcher.Func) : null,
DataFunc = bodyMatcher != null ? Map(bodyMatcher.DataFunc) : null
}
@@ -149,84 +147,16 @@ namespace WireMock.Serialization
return newDictionary;
}
private static MatcherModel[] Map([CanBeNull] IEnumerable<IMatcher> matchers)
{
if (matchers == null || !matchers.Any())
{
return null;
}
return matchers.Select(Map).Where(x => x != null).ToArray();
}
private static MatcherModel Map([CanBeNull] IMatcher matcher)
{
if (matcher == null)
{
return null;
}
var patterns = matcher.GetPatterns();
return new MatcherModel
{
Name = matcher.GetName(),
Pattern = patterns.Length == 1 ? patterns.First() : null,
Patterns = patterns.Length > 1 ? patterns : null
};
}
private static string[] Map<T>([CanBeNull] IEnumerable<Func<T, bool>> funcs)
{
if (funcs == null || !funcs.Any())
return null;
return funcs.Select(Map).Where(x => x != null).ToArray();
return funcs?.Select(Map).Where(x => x != null).ToArray();
}
private static string Map<T>([CanBeNull] Func<T, bool> func)
{
return func?.ToString();
}
public static IMatcher Map([CanBeNull] MatcherModel matcher)
{
if (matcher == null)
return null;
var parts = matcher.Name.Split('.');
string matcherName = parts[0];
string matcherType = parts.Length > 1 ? parts[1] : null;
string[] patterns = matcher.Patterns ?? new[] { matcher.Pattern };
switch (matcherName)
{
case "ExactMatcher":
return new ExactMatcher(patterns);
case "RegexMatcher":
return new RegexMatcher(patterns);
case "JsonPathMatcher":
return new JsonPathMatcher(patterns);
case "XPathMatcher":
return new XPathMatcher(matcher.Pattern);
case "WildcardMatcher":
return new WildcardMatcher(patterns, matcher.IgnoreCase == true);
case "SimMetricsMatcher":
SimMetricType type = SimMetricType.Levenstein;
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported.");
return new SimMetricsMatcher(matcher.Pattern, type);
default:
throw new NotSupportedException($"Matcher '{matcherName}' is not supported.");
}
}
}
}

View File

@@ -0,0 +1,35 @@
using System.Collections.Generic;
using System.Linq;
using JetBrains.Annotations;
using WireMock.Admin.Mappings;
using WireMock.Matchers;
namespace WireMock.Serialization
{
internal static class MatcherMapper
{
public static MatcherModel[] Map([CanBeNull] IEnumerable<IMatcher> matchers)
{
return matchers?.Select(Map).Where(x => x != null).ToArray();
}
public static MatcherModel Map([CanBeNull] IMatcher matcher)
{
if (matcher == null)
{
return null;
}
string[] patterns = matcher is IStringMatcher stringMatcher ? stringMatcher.GetPatterns() : new string[0];
bool? ignorecase = matcher is IIgnoreCaseMatcher ignoreCaseMatcher ? ignoreCaseMatcher.IgnoreCase : (bool?)null;
return new MatcherModel
{
IgnoreCase = ignorecase,
Name = matcher.GetName(),
Pattern = patterns.Length == 1 ? patterns.First() : null,
Patterns = patterns.Length > 1 ? patterns : null
};
}
}
}

View File

@@ -0,0 +1,55 @@
using System;
using JetBrains.Annotations;
using SimMetrics.Net;
using WireMock.Admin.Mappings;
using WireMock.Matchers;
namespace WireMock.Serialization
{
internal static class MatcherModelMapper
{
public static IMatcher Map([CanBeNull] MatcherModel matcher)
{
if (matcher == null)
{
return null;
}
string[] parts = matcher.Name.Split('.');
string matcherName = parts[0];
string matcherType = parts.Length > 1 ? parts[1] : null;
string[] patterns = matcher.Patterns ?? new[] { matcher.Pattern };
switch (matcherName)
{
case "ExactMatcher":
return new ExactMatcher(patterns);
case "RegexMatcher":
return new RegexMatcher(patterns, matcher.IgnoreCase == true);
case "JsonPathMatcher":
return new JsonPathMatcher(patterns);
case "XPathMatcher":
return new XPathMatcher(matcher.Pattern);
case "WildcardMatcher":
return new WildcardMatcher(patterns, matcher.IgnoreCase == true);
case "SimMetricsMatcher":
SimMetricType type = SimMetricType.Levenstein;
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
{
throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported.");
}
return new SimMetricsMatcher(matcher.Pattern, type);
default:
throw new NotSupportedException($"Matcher '{matcherName}' is not supported.");
}
}
}
}

View File

@@ -17,6 +17,7 @@ using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.ResponseProviders;
using WireMock.Serialization;
using WireMock.Settings;
using WireMock.Util;
@@ -113,7 +114,7 @@ namespace WireMock.Server
foreach (string filename in Directory.EnumerateFiles(folder).OrderBy(f => f))
{
Log.InfoFormat("Reading Static MappingFile : '{0}'", filename);
_logger.Info("Reading Static MappingFile : '{0}'", filename);
ReadStaticMappingAndAddOrUpdate(filename);
}
}
@@ -135,22 +136,22 @@ namespace WireMock.Server
return;
}
Log.InfoFormat("Watching folder '{0}' for new, updated and deleted MappingFiles.", folder);
_logger.Info("Watching folder '{0}' for new, updated and deleted MappingFiles.", folder);
var watcher = new EnhancedFileSystemWatcher(folder, "*.json", 1000);
watcher.Created += (sender, args) =>
{
Log.InfoFormat("New MappingFile created : '{0}'", args.FullPath);
_logger.Info("New MappingFile created : '{0}'", args.FullPath);
ReadStaticMappingAndAddOrUpdate(args.FullPath);
};
watcher.Changed += (sender, args) =>
{
Log.InfoFormat("New MappingFile updated : '{0}'", args.FullPath);
_logger.Info("New MappingFile updated : '{0}'", args.FullPath);
ReadStaticMappingAndAddOrUpdate(args.FullPath);
};
watcher.Deleted += (sender, args) =>
{
Log.InfoFormat("New MappingFile deleted : '{0}'", args.FullPath);
_logger.Info("New MappingFile deleted : '{0}'", args.FullPath);
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(args.FullPath);
if (Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
@@ -229,9 +230,10 @@ namespace WireMock.Server
requestMessage.Query.Loop((key, value) => request.WithParam(key, value.ToArray()));
requestMessage.Cookies.Loop((key, value) => request.WithCookie(key, value));
var allBlackListedHeaders = new List<string>(blacklistedHeaders) { "Cookie" };
requestMessage.Headers.Loop((key, value) =>
{
if (!blacklistedHeaders.Any(b => string.Equals(key, b, StringComparison.OrdinalIgnoreCase)))
if (!allBlackListedHeaders.Any(b => string.Equals(key, b, StringComparison.OrdinalIgnoreCase)))
{
request.WithHeader(key, value.ToArray());
}
@@ -288,7 +290,7 @@ namespace WireMock.Server
if (mapping == null)
{
Log.Warn("HttpStatusCode set to 404 : Mapping not found");
_logger.Warn("HttpStatusCode set to 404 : Mapping not found");
return new ResponseMessage { StatusCode = 404, Body = "Mapping not found" };
}
@@ -343,7 +345,7 @@ namespace WireMock.Server
string filename = !string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToString();
string filePath = Path.Combine(folder, filename + ".json");
Log.InfoFormat("Saving Mapping to file {0}", filePath);
_logger.Info("Saving Mapping to file {0}", filePath);
File.WriteAllText(filePath, JsonConvert.SerializeObject(model, _settings));
}
@@ -374,12 +376,12 @@ namespace WireMock.Server
}
catch (ArgumentException a)
{
Log.Error("HttpStatusCode set to 400", a);
_logger.Error("HttpStatusCode set to 400 {0}", a);
return new ResponseMessage { StatusCode = 400, Body = a.Message };
}
catch (Exception e)
{
Log.Error("HttpStatusCode set to 500", e);
_logger.Error("HttpStatusCode set to 500 {0}", e);
return new ResponseMessage { StatusCode = 500, Body = e.ToString() };
}
@@ -449,8 +451,8 @@ namespace WireMock.Server
if (entry == null)
{
Log.Warn("HttpStatusCode set to 404 : Request not found");
return new ResponseMessage {StatusCode = 404, Body = "Request not found"};
_logger.Warn("HttpStatusCode set to 404 : Request not found");
return new ResponseMessage { StatusCode = 404, Body = "Request not found" };
}
var model = ToLogEntryModel(entry);
@@ -606,7 +608,7 @@ namespace WireMock.Server
var clientIPModel = JsonUtils.ParseJTokenToObject<ClientIPModel>(requestModel.ClientIP);
if (clientIPModel?.Matchers != null)
{
requestBuilder = requestBuilder.WithPath(clientIPModel.Matchers.Select(MappingConverter.Map).ToArray());
requestBuilder = requestBuilder.WithPath(clientIPModel.Matchers.Select(MatcherModelMapper.Map).Cast<IStringMatcher>().ToArray());
}
}
}
@@ -623,7 +625,7 @@ namespace WireMock.Server
var pathModel = JsonUtils.ParseJTokenToObject<PathModel>(requestModel.Path);
if (pathModel?.Matchers != null)
{
requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(MappingConverter.Map).ToArray());
requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(MatcherModelMapper.Map).Cast<IStringMatcher>().ToArray());
}
}
}
@@ -640,7 +642,7 @@ namespace WireMock.Server
var urlModel = JsonUtils.ParseJTokenToObject<UrlModel>(requestModel.Url);
if (urlModel?.Matchers != null)
{
requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(MappingConverter.Map).ToArray());
requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(MatcherModelMapper.Map).Cast<IStringMatcher>().ToArray());
}
}
}
@@ -654,7 +656,7 @@ namespace WireMock.Server
{
foreach (var headerModel in requestModel.Headers.Where(h => h.Matchers != null))
{
requestBuilder = requestBuilder.WithHeader(headerModel.Name, headerModel.Matchers.Select(MappingConverter.Map).ToArray());
requestBuilder = requestBuilder.WithHeader(headerModel.Name, headerModel.Matchers.Select(MatcherModelMapper.Map).Cast<IStringMatcher>().ToArray());
}
}
@@ -662,21 +664,21 @@ namespace WireMock.Server
{
foreach (var cookieModel in requestModel.Cookies.Where(c => c.Matchers != null))
{
requestBuilder = requestBuilder.WithCookie(cookieModel.Name, cookieModel.Matchers.Select(MappingConverter.Map).ToArray());
requestBuilder = requestBuilder.WithCookie(cookieModel.Name, cookieModel.Matchers.Select(MatcherModelMapper.Map).Cast<IStringMatcher>().ToArray());
}
}
if (requestModel.Params != null)
{
foreach (var paramModel in requestModel.Params.Where(p => p.Values != null))
foreach (var paramModel in requestModel.Params)
{
requestBuilder = requestBuilder.WithParam(paramModel.Name, paramModel.Values.ToArray());
requestBuilder = paramModel.Values == null ? requestBuilder.WithParam(paramModel.Name) : requestBuilder.WithParam(paramModel.Name, paramModel.Values.ToArray());
}
}
if (requestModel.Body?.Matcher != null)
{
var bodyMatcher = MappingConverter.Map(requestModel.Body.Matcher);
var bodyMatcher = MatcherModelMapper.Map(requestModel.Body.Matcher);
requestBuilder = requestBuilder.WithBody(bodyMatcher);
}

View File

@@ -1,20 +1,20 @@
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using JetBrains.Annotations;
using log4net;
using Newtonsoft.Json;
using WireMock.Http;
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.Settings;
using WireMock.Validation;
using WireMock.Owin;
using WireMock.ResponseProviders;
namespace WireMock.Server
{
@@ -23,7 +23,7 @@ namespace WireMock.Server
/// </summary>
public partial class FluentMockServer : IDisposable
{
private static readonly ILog Log = LogManager.GetLogger(typeof(FluentMockServer));
private readonly IWireMockLogger _logger;
private const int ServerStartDelay = 100;
private readonly IOwinSelfHost _httpServer;
private readonly WireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
@@ -158,7 +158,10 @@ namespace WireMock.Server
private FluentMockServer(IFluentMockServerSettings settings)
{
Log.DebugFormat("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
settings.Logger = settings.Logger ?? new WireMockConsoleLogger();
_logger = settings.Logger;
_logger.Debug("WireMock.Net server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
if (settings.Urls != null)
{
@@ -172,14 +175,13 @@ namespace WireMock.Server
_options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit;
_options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit;
_options.Logger = _logger;
#if NETSTANDARD
_httpServer = new AspNetCoreSelfHost(_options, Urls);
#else
_httpServer = new OwinSelfHost(_options, Urls);
#endif
IsStarted = _httpServer.IsStarted;
Ports = _httpServer.Ports;
_httpServer.StartAsync();
@@ -187,6 +189,8 @@ namespace WireMock.Server
// Fix for 'Bug: Server not listening after Start() returns (on macOS)'
Task.Delay(ServerStartDelay).Wait();
IsStarted = _httpServer.IsStarted;
if (settings.AllowPartialMapping == true)
{
AllowPartialMapping();
@@ -318,7 +322,7 @@ namespace WireMock.Server
[PublicAPI]
public void AllowPartialMapping(bool allow = true)
{
Log.InfoFormat("AllowPartialMapping is set to {0}", allow);
_logger.Info("AllowPartialMapping is set to {0}", allow);
_options.AllowPartialMapping = allow;
}

View File

@@ -1,4 +1,5 @@
using System;
using WireMock.ResponseProviders;
namespace WireMock.Server
{

View File

@@ -1,5 +1,6 @@
using System;
using WireMock.Matchers.Request;
using WireMock.ResponseProviders;
namespace WireMock.Server
{

View File

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

View File

@@ -1,4 +1,6 @@
using System;
using JetBrains.Annotations;
using WireMock.Logging;
namespace WireMock.Settings
{
@@ -10,77 +12,98 @@ namespace WireMock.Settings
/// <summary>
/// Gets or sets the port.
/// </summary>
[PublicAPI]
int? Port { get; set; }
/// <summary>
/// Gets or sets the use SSL.
/// </summary>
// ReSharper disable once InconsistentNaming
[PublicAPI]
bool? UseSSL { get; set; }
/// <summary>
/// Gets or sets wether to start admin interface.
/// </summary>
[PublicAPI]
bool? StartAdminInterface { get; set; }
/// <summary>
/// Gets or sets if the static mappings should be read at startup.
/// </summary>
[PublicAPI]
bool? ReadStaticMappings { get; set; }
/// <summary>
/// Watch the static mapping files + folder for changes when running.
/// </summary>
[PublicAPI]
bool? WatchStaticMappings { get; set; }
/// <summary>
/// Gets or sets if the proxy and record settings.
/// </summary>
[PublicAPI]
IProxyAndRecordSettings ProxyAndRecordSettings { get; set; }
/// <summary>
/// Gets or sets the urls.
/// </summary>
[PublicAPI]
string[] Urls { get; set; }
/// <summary>
/// StartTimeout
/// </summary>
[PublicAPI]
int StartTimeout { get; set; }
/// <summary>
/// Allow Partial Mapping (default set to false).
/// </summary>
[PublicAPI]
bool? AllowPartialMapping { get; set; }
/// <summary>
/// The username needed for __admin access.
/// </summary>
[PublicAPI]
string AdminUsername { get; set; }
/// <summary>
/// The password needed for __admin access.
/// </summary>
[PublicAPI]
string AdminPassword { get; set; }
/// <summary>
/// The RequestLog expiration in hours (optional).
/// </summary>
[PublicAPI]
int? RequestLogExpirationDuration { get; set; }
/// <summary>
/// The MaxRequestLog count (optional).
/// </summary>
[PublicAPI]
int? MaxRequestLogCount { get; set; }
/// <summary>
/// Action which is called (with the IAppBuilder or IApplicationBuilder) before the internal WireMockMiddleware is initialized. [Optional]
/// </summary>
[PublicAPI]
Action<object> PreWireMockMiddlewareInit { get; set; }
/// <summary>
/// Action which is called (with the IAppBuilder or IApplicationBuilder) after the internal WireMockMiddleware is initialized. [Optional]
/// </summary>
[PublicAPI]
Action<object> PostWireMockMiddlewareInit { get; set; }
/// <summary>
/// The IWireMockLogger which logs Debug, Info, Warning or Error
/// </summary>
[PublicAPI]
IWireMockLogger Logger { get; set; }
}
}

View File

@@ -1,6 +1,7 @@
using System.Collections.Generic;
using System.Linq;
using HandlebarsDotNet;
using Newtonsoft.Json;
using WireMock.Util;
namespace WireMock.Transformers
@@ -9,13 +10,31 @@ namespace WireMock.Transformers
{
public static ResponseMessage Transform(RequestMessage requestMessage, ResponseMessage original)
{
var responseMessage = new ResponseMessage { StatusCode = original.StatusCode, BodyOriginal = original.Body };
bool bodyIsJson = original.BodyAsJson != null;
var responseMessage = new ResponseMessage { StatusCode = original.StatusCode };
if (!bodyIsJson)
{
responseMessage.BodyOriginal = original.Body;
}
var template = new { request = requestMessage };
// Body
var templateBody = Handlebars.Compile(original.Body);
responseMessage.Body = templateBody(template);
string body = bodyIsJson ? JsonConvert.SerializeObject(original.BodyAsJson) : original.Body;
if (body != null)
{
var templateBody = Handlebars.Compile(body);
if (!bodyIsJson)
{
responseMessage.Body = templateBody(template);
}
else
{
responseMessage.BodyAsJson = JsonConvert.DeserializeObject(templateBody(template));
}
}
// Headers
var newHeaders = new Dictionary<string, WireMockList<string>>();

View File

@@ -10,7 +10,13 @@ namespace WireMock.Util
{
internal static class BodyParser
{
private static readonly string[] TextContentTypes = { "text/", "application/xml", "application/javascript", "application/typescript", "application/xhtml+xml" };
private static readonly string[] TextContentTypes =
{
"text/",
"application/javascript", "application/typescript",
"application/xml", "application/xhtml+xml",
"application/x-www-form-urlencoded"
};
private static async Task<Tuple<string, Encoding>> ReadStringAsync(Stream stream)
{

View File

@@ -3,7 +3,7 @@
<PropertyGroup>
<Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description>
<AssemblyTitle>WireMock.Net</AssemblyTitle>
<Version>1.0.3.2</Version>
<Version>1.0.3.9</Version>
<Authors>Alexandre Victoor;Stef Heyenrath</Authors>
<TargetFrameworks>net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
@@ -32,6 +32,10 @@
<DefineConstants>NETSTANDARD</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Remove="Util\NamedReaderWriterLocker.cs" />
</ItemGroup>
<ItemGroup>
<None Remove="Server\FluentMockServer.cs~RF44936b9f.TMP" />
</ItemGroup>
@@ -45,7 +49,6 @@
<PackageReference Include="SimMetrics.Net" Version="1.0.4" />
<PackageReference Include="System.Net.Http" Version="4.3.3" />
<PackageReference Include="RestEase" Version="1.4.4" />
<PackageReference Include="log4net" Version="2.0.8" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
@@ -55,7 +58,11 @@
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.3" />
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.4" />
<PackageReference Include="Microsoft.Owin" Version="4.0.0" />
<PackageReference Include="Microsoft.Owin.Host.HttpListener" Version="4.0.0" />
<PackageReference Include="Microsoft.Owin.Hosting" Version="4.0.0" />
<PackageReference Include="System.Net.Http" Version="4.3.3" />
<PackageReference Include="XPath2" Version="1.0.5.1" />
</ItemGroup>

View File

@@ -6,6 +6,7 @@ using NFluent;
using RestEase;
using WireMock.Admin.Mappings;
using WireMock.Client;
using WireMock.Logging;
using WireMock.Server;
using WireMock.Settings;
using Xunit;
@@ -25,7 +26,7 @@ namespace WireMock.Net.Tests
public async Task IFluentMockServerAdmin_FindRequestsAsync()
{
// given
_server = FluentMockServer.Start(new FluentMockServerSettings { StartAdminInterface = true });
_server = FluentMockServer.Start(new FluentMockServerSettings { StartAdminInterface = true, Logger = new WireMockNullLogger() });
var serverUrl = "http://localhost:" + _server.Ports[0];
await new HttpClient().GetAsync(serverUrl + "/foo");
var api = RestClient.For<IFluentMockServerAdmin>(serverUrl);
@@ -45,7 +46,7 @@ namespace WireMock.Net.Tests
public async Task IFluentMockServerAdmin_GetRequestsAsync()
{
// given
_server = FluentMockServer.Start(new FluentMockServerSettings { StartAdminInterface = true });
_server = FluentMockServer.Start(new FluentMockServerSettings { StartAdminInterface = true, Logger = new WireMockNullLogger() });
var serverUrl = "http://localhost:" + _server.Ports[0];
await new HttpClient().GetAsync(serverUrl + "/foo");
var api = RestClient.For<IFluentMockServerAdmin>(serverUrl);

View File

@@ -89,13 +89,12 @@ namespace WireMock.Net.Tests
}
[Fact]
public void FluentMockServer_Admin_Mappings_Get()
public void FluentMockServer_Admin_Mappings_WithGuid_Get()
{
Guid guid = Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05");
_server = FluentMockServer.Start();
_server.Given(Request.Create().WithPath("/foo1").UsingGet())
.WithGuid(guid)
_server.Given(Request.Create().WithPath("/foo1").UsingGet()).WithGuid(guid)
.RespondWith(Response.Create().WithStatusCode(201).WithBody("1"));
_server.Given(Request.Create().WithPath("/foo2").UsingGet())
@@ -105,6 +104,19 @@ namespace WireMock.Net.Tests
Check.That(mappings).HasSize(2);
}
[Fact]
public void FluentMockServer_Admin_Mappings_WithGuidAsString_Get()
{
string guid = "90356dba-b36c-469a-a17e-669cd84f1f05";
_server = FluentMockServer.Start();
_server.Given(Request.Create().WithPath("/foo1").UsingGet()).WithGuid(guid)
.RespondWith(Response.Create().WithStatusCode(201).WithBody("1"));
var mappings = _server.Mappings.ToArray();
Check.That(mappings).HasSize(1);
}
[Fact]
public void FluentMockServer_Admin_Mappings_Add_SameGuid()
{
@@ -220,6 +232,27 @@ namespace WireMock.Net.Tests
Check.That(response).IsEqualTo("Hello world!");
}
[Fact]
public async Task FluentMockServer_Should_respond_to_request_bodyAsCallback()
{
// given
_server = FluentMockServer.Start();
_server
.Given(Request.Create()
.WithPath("/foo")
.UsingGet())
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithBody(req => $"{{ path: '{req.Path}' }}"));
// when
var response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
// then
Check.That(response).IsEqualTo("{ path: '/foo' }");
}
[Fact]
public async Task FluentMockServer_Should_respond_to_request_bodyAsBase64()
{
@@ -432,6 +465,23 @@ namespace WireMock.Net.Tests
Check.That(requestLoggedB.RequestMessage.Path).EndsWith("/foo3");
}
[Fact]
public async Task FluentMockServer_Should_respond_to_request_callback()
{
// Assign
_server = FluentMockServer.Start();
_server
.Given(Request.Create().WithPath("/foo").UsingGet())
.RespondWith(Response.Create().WithCallback(req => new ResponseMessage { Body = req.Path + "Bar" }));
// Act
string response = await new HttpClient().GetStringAsync("http://localhost:" + _server.Ports[0] + "/foo");
// Assert
Check.That(response).IsEqualTo("/fooBar");
}
public void Dispose()
{
_server?.Stop();

View File

@@ -0,0 +1,61 @@
using NFluent;
using WireMock.Matchers;
using Xunit;
namespace WireMock.Net.Tests.Matchers
{
public class ExactMatcherTests
{
[Fact]
public void ExactMatcher_GetName()
{
// Assign
var matcher = new ExactMatcher("X");
// Act
string name = matcher.GetName();
// Assert
Check.That(name).Equals("ExactMatcher");
}
[Fact]
public void ExactMatcher_GetPatterns()
{
// Assign
var matcher = new ExactMatcher("X");
// Act
string[] patterns = matcher.GetPatterns();
// Assert
Check.That(patterns).ContainsExactly("X");
}
[Fact]
public void ExactMatcher_IsMatch_MultiplePatterns()
{
// Assign
var matcher = new ExactMatcher("x", "y");
// Act
double result = matcher.IsMatch("x");
// Assert
Check.That(result).IsEqualTo(0.5d);
}
[Fact]
public void Request_WithBodyExactMatcher_false()
{
// Assign
var matcher = new ExactMatcher("cat");
// Act
double result = matcher.IsMatch("caR");
// Assert
Check.That(result).IsStrictlyLessThan(1.0);
}
}
}

View File

@@ -0,0 +1,23 @@
using NFluent;
using WireMock.Matchers;
using Xunit;
namespace WireMock.Net.Tests.Matchers
{
public class ExactObjectMatcherTests
{
[Fact]
public void ExactObjectMatcher_GetName()
{
// Assign
object obj = 1;
// Act
var matcher = new ExactObjectMatcher(obj);
string name = matcher.GetName();
// Assert
Check.That(name).Equals("ExactObjectMatcher");
}
}
}

View File

@@ -0,0 +1,35 @@
using NFluent;
using WireMock.Matchers;
using Xunit;
namespace WireMock.Net.Tests.Matchers
{
public class JsonPathMatcherTests
{
[Fact]
public void JsonPathMatcher_GetName()
{
// Assign
var matcher = new JsonPathMatcher("X");
// Act
string name = matcher.GetName();
// Assert
Check.That(name).Equals("JsonPathMatcher");
}
[Fact]
public void JsonPathMatcher_GetPatterns()
{
// Assign
var matcher = new JsonPathMatcher("X");
// Act
string[] patterns = matcher.GetPatterns();
// Assert
Check.That(patterns).ContainsExactly("X");
}
}
}

View File

@@ -0,0 +1,74 @@
using NFluent;
using WireMock.Matchers;
using Xunit;
namespace WireMock.Net.Tests.Matchers
{
public class RegexMatcherTests
{
[Fact]
public void RegexMatcher_GetName()
{
// Assign
var matcher = new RegexMatcher("");
// Act
string name = matcher.GetName();
// Assert
Check.That(name).Equals("RegexMatcher");
}
[Fact]
public void RegexMatcher_GetPatterns()
{
// Assign
var matcher = new RegexMatcher("X");
// Act
string[] patterns = matcher.GetPatterns();
// Assert
Check.That(patterns).ContainsExactly("X");
}
[Fact]
public void RegexMatcher_IsMatch()
{
// Assign
var matcher = new RegexMatcher("H.*o");
// Act
double result = matcher.IsMatch("Hello world!");
// Assert
Check.That(result).IsEqualTo(1.0d);
}
[Fact]
public void RegexMatcher_IsMatch_NullInput()
{
// Assign
var matcher = new RegexMatcher("H.*o");
// Act
double result = matcher.IsMatch(null);
// Assert
Check.That(result).IsEqualTo(0.0d);
}
[Fact]
public void RegexMatcher_IsMatch_IgnoreCase()
{
// Assign
var matcher = new RegexMatcher("H.*o", true);
// Act
double result = matcher.IsMatch("hello world!");
// Assert
Check.That(result).IsEqualTo(1.0d);
}
}
}

View File

@@ -0,0 +1,61 @@
using NFluent;
using WireMock.Matchers;
using Xunit;
namespace WireMock.Net.Tests.Matchers
{
public class SimMetricsMatcherTests
{
[Fact]
public void SimMetricsMatcher_GetName()
{
// Assign
var matcher = new SimMetricsMatcher("X");
// Act
string name = matcher.GetName();
// Assert
Check.That(name).Equals("SimMetricsMatcher.Levenstein");
}
[Fact]
public void SimMetricsMatcher_GetPatterns()
{
// Assign
var matcher = new SimMetricsMatcher("X");
// Act
string[] patterns = matcher.GetPatterns();
// Assert
Check.That(patterns).ContainsExactly("X");
}
[Fact]
public void SimMetricsMatcher_IsMatch_1()
{
// Assign
var matcher = new SimMetricsMatcher("The cat walks in the street.");
// Act
double result = matcher.IsMatch("The car drives in the street.");
// Assert
Check.That(result).IsStrictlyLessThan(1.0).And.IsStrictlyGreaterThan(0.5);
}
[Fact]
public void SimMetricsMatcher_IsMatch_2()
{
// Assign
var matcher = new SimMetricsMatcher("The cat walks in the street.");
// Act
double result = matcher.IsMatch("Hello");
// Assert
Check.That(result).IsStrictlyLessThan(0.1).And.IsStrictlyGreaterThan(0.05);
}
}
}

View File

@@ -0,0 +1,87 @@
using NFluent;
using WireMock.Matchers;
using Xunit;
namespace WireMock.Net.Tests.Matchers
{
public class WildcardMatcherTest
{
[Fact]
public void WildcardMatcher_IsMatch_Positive()
{
var tests = new[]
{
new {p = "*", i = ""},
new {p = "?", i = " "},
new {p = "*", i = "a"},
new {p = "*", i = "ab"},
new {p = "?", i = "a"},
new {p = "*?", i = "abc"},
new {p = "?*", i = "abc"},
new {p = "abc", i = "abc"},
new {p = "abc*", i = "abc"},
new {p = "abc*", i = "abcd"},
new {p = "*abc*", i = "abc"},
new {p = "*a*bc*", i = "abc"},
new {p = "*a*b?", i = "aXXXbc"}
};
foreach (var test in tests)
{
var matcher = new WildcardMatcher(test.p);
Check.That(matcher.IsMatch(test.i)).IsEqualTo(1.0d);
}
}
[Fact]
public void WildcardMatcher_IsMatch_Negative()
{
var tests = new[]
{
new {p = "*a", i = ""},
new {p = "a*", i = ""},
new {p = "?", i = ""},
new {p = "*b*", i = "a"},
new {p = "b*a", i = "ab"},
new {p = "??", i = "a"},
new {p = "*?", i = ""},
new {p = "??*", i = "a"},
new {p = "*abc", i = "abX"},
new {p = "*abc*", i = "Xbc"},
new {p = "*a*bc*", i = "ac"}
};
foreach (var test in tests)
{
var matcher = new WildcardMatcher(test.p);
Check.That(matcher.IsMatch(test.i)).IsEqualTo(0.0);
}
}
[Fact]
public void WildcardMatcher_GetName()
{
// Assign
var matcher = new WildcardMatcher("x");
// Act
string name = matcher.GetName();
// Assert
Check.That(name).Equals("WildcardMatcher");
}
[Fact]
public void WildcardMatcher_GetPatterns()
{
// Assign
var matcher = new WildcardMatcher("x");
// Act
string[] patterns = matcher.GetPatterns();
// Assert
Check.That(patterns).ContainsExactly("x");
}
}
}

View File

@@ -0,0 +1,35 @@
using NFluent;
using WireMock.Matchers;
using Xunit;
namespace WireMock.Net.Tests.Matchers
{
public class XPathMatcherTests
{
[Fact]
public void XPathMatcher_GetName()
{
// Assign
var matcher = new XPathMatcher("X");
// Act
string name = matcher.GetName();
// Assert
Check.That(name).Equals("XPathMatcher");
}
[Fact]
public void XPathMatcher_GetPatterns()
{
// Assign
var matcher = new XPathMatcher("X");
// Act
string[] patterns = matcher.GetPatterns();
// Assert
Check.That(patterns).ContainsExactly("X");
}
}
}

View File

@@ -0,0 +1,83 @@
using System;
using System.Collections.Generic;
using System.Linq;
using Moq;
using NFluent;
using WireMock.Matchers.Request;
using Xunit;
namespace WireMock.Net.Tests.RequestMatchers
{
public class RequestMessageCompositeMatcherTests
{
private class Helper : RequestMessageCompositeMatcher
{
public Helper(IEnumerable<IRequestMatcher> requestMatchers, CompositeMatcherType type = CompositeMatcherType.And) : base(requestMatchers, type)
{
}
}
[Fact]
public void RequestMessageCompositeMatcher_GetMatchingScore_EmptyArray()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1");
var matcher = new Helper(Enumerable.Empty<IRequestMatcher>());
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(0.0d);
}
[Fact]
public void RequestMessageCompositeMatcher_GetMatchingScore_CompositeMatcherType_And()
{
// Assign
var requestMatcher1Mock = new Mock<IRequestMatcher>();
requestMatcher1Mock.Setup(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>())).Returns(1.0d);
var requestMatcher2Mock = new Mock<IRequestMatcher>();
requestMatcher2Mock.Setup(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>())).Returns(0.8d);
var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1");
var matcher = new Helper(new[] { requestMatcher1Mock.Object, requestMatcher2Mock.Object });
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(0.9d);
// Verify
requestMatcher1Mock.Verify(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>()), Times.Once);
requestMatcher2Mock.Verify(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>()), Times.Once);
}
[Fact]
public void RequestMessageCompositeMatcher_GetMatchingScore_CompositeMatcherType_Or()
{
// Assign
var requestMatcher1Mock = new Mock<IRequestMatcher>();
requestMatcher1Mock.Setup(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>())).Returns(1.0d);
var requestMatcher2Mock = new Mock<IRequestMatcher>();
requestMatcher2Mock.Setup(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>())).Returns(0.8d);
var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1");
var matcher = new Helper(new[] { requestMatcher1Mock.Object, requestMatcher2Mock.Object }, CompositeMatcherType.Or);
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
// Verify
requestMatcher1Mock.Verify(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>()), Times.Once);
requestMatcher2Mock.Verify(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>()), Times.Once);
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using NFluent;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using Xunit;
namespace WireMock.Net.Tests.RequestMatchers
{
public class RequestMessageCookieMatcherTests
{
[Fact]
public void RequestMessageCookieMatcher_GetMatchingScore_IStringMatcher_Match()
{
// Assign
var cookies = new Dictionary<string, string> { { "cook", "x" } };
var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1", null, null, cookies);
var matcher = new RequestMessageCookieMatcher("cook", new ExactMatcher("x"));
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
}
[Fact]
public void RequestMessageCookieMatcher_GetMatchingScore_Func_Match()
{
// Assign
var cookies = new Dictionary<string, string> { { "cook", "x" } };
var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1", null, null, cookies);
var matcher = new RequestMessageCookieMatcher(x => x.ContainsKey("cook"));
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
}
}
}

View File

@@ -0,0 +1,44 @@
using System;
using System.Collections.Generic;
using NFluent;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using Xunit;
namespace WireMock.Net.Tests.RequestMatchers
{
public class RequestMessageHeaderMatcherTests
{
[Fact]
public void RequestMessageHeaderMatcher_GetMatchingScore_IStringMatcher_Match()
{
// Assign
var headers = new Dictionary<string, string[]> { { "h", new [] { "x" } } };
var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1", null, headers);
var matcher = new RequestMessageHeaderMatcher("h", new ExactMatcher("x"));
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
}
[Fact]
public void RequestMessageHeaderMatcher_GetMatchingScore_Func_Match()
{
// Assign
var headers = new Dictionary<string, string[]> { { "h", new[] { "x" } } };
var requestMessage = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.1", null, headers);
var matcher = new RequestMessageHeaderMatcher(x => x.ContainsKey("h"));
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
}
}
}

View File

@@ -0,0 +1,85 @@
using System;
using NFluent;
using WireMock.Matchers.Request;
using Xunit;
namespace WireMock.Net.Tests.RequestMatchers
{
public class RequestMessageParamMatcherTests
{
[Fact]
public void RequestMessageParamMatcher_GetMatchingScore_AllMatch()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key=test1,test2"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher("key", new[] { "test1", "test2" });
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
}
[Fact]
public void RequestMessageParamMatcher_GetMatchingScore_PartialMatch()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key=test0,test2"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher("key", new[] { "test1", "test2" });
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(0.5d);
}
[Fact]
public void RequestMessageParamMatcher_GetMatchingScore_OnlyKeyPresent()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher("key", new[] { "test1", "test2" });
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(0.0d);
}
[Fact]
public void RequestMessageParamMatcher_GetMatchingScore_OnlyKeyPresent_WithNull()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher("key");
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
}
[Fact]
public void RequestMessageParamMatcher_GetMatchingScore_OnlyKeyPresent_WithEmptyArray()
{
// Assign
var requestMessage = new RequestMessage(new Uri("http://localhost?key"), "GET", "127.0.0.1");
var matcher = new RequestMessageParamMatcher("key", new string[] { });
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
Check.That(score).IsEqualTo(1.0d);
}
}
}

View File

@@ -1,17 +1,15 @@
using System;
using System.Text;
using NFluent;
using Xunit;
namespace WireMock.Net.Tests
{
//[TestFixture]
public class RequestMessageTests
{
private const string ClientIp = "::1";
[Fact]
public void Should_handle_empty_query()
public void RequestMessage_ParseQuery_NoKeys()
{
// given
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp);
@@ -21,17 +19,36 @@ namespace WireMock.Net.Tests
}
[Fact]
public void Should_parse_query_params()
public void RequestMessage_ParseQuery_SingleKey_SingleValue()
{
// given
string bodyAsString = "whatever";
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
var request = new RequestMessage(new Uri("http://localhost?foo=bar&multi=1&multi=2"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
// Assign
var request = new RequestMessage(new Uri("http://localhost?foo=bar"), "POST", ClientIp);
// then
Check.That(request.GetParameter("foo")).Contains("bar");
Check.That(request.GetParameter("multi")).Contains("1");
Check.That(request.GetParameter("multi")).Contains("2");
// Assert
Check.That(request.GetParameter("foo")).ContainsExactly("bar");
}
[Fact]
public void RequestMessage_ParseQuery_MultipleKeys_MultipleValues()
{
// Assign
var request = new RequestMessage(new Uri("http://localhost?key=1&key=2"), "POST", ClientIp);
// Assert
Check.That(request.GetParameter("key")).Contains("1");
Check.That(request.GetParameter("key")).Contains("2");
}
[Fact]
public void RequestMessage_ParseQuery_SingleKey_MultipleValues()
{
// Assign
var request = new RequestMessage(new Uri("http://localhost?key=1,2&foo=bar&key=3"), "POST", ClientIp);
// Assert
Check.That(request.GetParameter("key")).Contains("1");
Check.That(request.GetParameter("key")).Contains("2");
Check.That(request.GetParameter("key")).Contains("3");
}
}
}

View File

@@ -123,20 +123,6 @@ namespace WireMock.Net.Tests
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Should_specify_requests_matching_given_paramNoValue()
{
// given
var spec = Request.Create().WithParam("bar");
// when
var request = new RequestMessage(new Uri("http://localhost/foo?bar"), "PUT", ClientIp);
// then
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Should_specify_requests_matching_given_param_func()
{

View File

@@ -1,10 +1,12 @@
using System;
using System.Collections.Generic;
using System.Text;
using Newtonsoft.Json;
using NFluent;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests
@@ -13,6 +15,60 @@ namespace WireMock.Net.Tests
{
private const string ClientIp = "::1";
[Fact]
public void Request_WithBody_FuncString()
{
// Assign
var requestBuilder = Request.Create().UsingAnyVerb().WithBody(b => b.Contains("b"));
// Act
var body = new BodyData
{
BodyAsString = "b"
};
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body);
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBody_FuncJson()
{
// Assign
var requestBuilder = Request.Create().UsingAnyVerb().WithBody(b => b != null);
// Act
var body = new BodyData
{
BodyAsJson = 123
};
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body);
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBody_FuncByteArray()
{
// Assign
var requestBuilder = Request.Create().UsingAnyVerb().WithBody((byte[] b) => b != null);
// Act
var body = new BodyData
{
BodyAsBytes = new byte[0]
};
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body);
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBodyExactMatcher()
{
@@ -29,70 +85,6 @@ namespace WireMock.Net.Tests
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBodyExactMatcher_multiplePatterns()
{
// given
var requestBuilder = Request.Create().UsingAnyVerb().WithBody(new ExactMatcher("cat", "dog"));
// when
string bodyAsString = "cat";
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
// then
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(0.5);
}
[Fact]
public void Request_WithBodyExactMatcher_false()
{
// given
var requestBuilder = Request.Create().UsingAnyVerb().WithBody(new ExactMatcher("cat"));
// when
string bodyAsString = "caR";
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
// then
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsStrictlyLessThan(1.0);
}
[Fact]
public void Request_WithBodySimMetricsMatcher1()
{
// given
var requestBuilder = Request.Create().UsingAnyVerb().WithBody(new SimMetricsMatcher("The cat walks in the street."));
// when
string bodyAsString = "The car drives in the street.";
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
// then
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsStrictlyLessThan(1.0).And.IsStrictlyGreaterThan(0.5);
}
[Fact]
public void Request_WithBodySimMetricsMatcher2()
{
// given
var requestBuilder = Request.Create().UsingAnyVerb().WithBody(new SimMetricsMatcher("The cat walks in the street."));
// when
string bodyAsString = "Hello";
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, body, bodyAsString, Encoding.UTF8);
// then
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsStrictlyLessThan(0.1).And.IsStrictlyGreaterThan(0.05);
}
[Fact]
public void Request_WithBodyWildcardMatcher()
{
@@ -109,22 +101,6 @@ namespace WireMock.Net.Tests
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBodyRegexMatcher()
{
// given
var spec = Request.Create().UsingAnyVerb().WithBody(new RegexMatcher("H.*o"));
// when
string bodyAsString = "Hello world!";
byte[] body = Encoding.UTF8.GetBytes(bodyAsString);
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, body, bodyAsString, Encoding.UTF8);
// then
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBodyXPathMatcher_true()
{
@@ -198,5 +174,108 @@ namespace WireMock.Net.Tests
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsNotEqualTo(1.0);
}
[Fact]
public void Request_WithBodyAsJson_Object_JsonPathMatcher_true()
{
// given
var spec = Request.Create().UsingAnyVerb().WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]"));
// when
string jsonString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }";
var bodyData = new BodyData
{
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
Encoding = Encoding.UTF8
};
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, bodyData);
// then
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBodyAsJson_Array_JsonPathMatcher_1()
{
// given
var spec = Request.Create().UsingAnyVerb().WithBody(new JsonPathMatcher("$.books[?(@.price < 10)]"));
// when
string jsonString = "{ \"books\": [ { \"category\": \"test1\", \"price\": 8.95 }, { \"category\": \"test2\", \"price\": 20 } ] }";
var bodyData = new BodyData
{
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
Encoding = Encoding.UTF8
};
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, bodyData);
// then
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBodyAsJson_Array_JsonPathMatcher_2()
{
// given
var spec = Request.Create().UsingAnyVerb().WithBody(new JsonPathMatcher("$..[?(@.Id == 1)]"));
// when
string jsonString = "{ \"Id\": 1, \"Name\": \"Test\" }";
var bodyData = new BodyData
{
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
Encoding = Encoding.UTF8
};
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, bodyData);
// then
var requestMatchResult = new RequestMatchResult();
double result = spec.GetMatchingScore(request, requestMatchResult);
Check.That(result).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBodyAsObject_ExactObjectMatcher_true()
{
// Assign
object body = DateTime.MinValue;
var requestBuilder = Request.Create().UsingAnyVerb().WithBody(body);
var bodyData = new BodyData
{
BodyAsJson = DateTime.MinValue
};
// Act
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, bodyData);
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithBodyAsBytes_ExactObjectMatcher_true()
{
// Assign
byte[] body = { 123 };
var requestBuilder = Request.Create().UsingAnyVerb().WithBody(body);
var bodyData = new BodyData
{
BodyAsBytes = new byte[] { 123 }
};
// Act
var request = new RequestMessage(new Uri("http://localhost/foo"), "PUT", ClientIp, bodyData);
// Assert
var requestMatchResult = new RequestMatchResult();
Check.That(requestBuilder.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using NFluent;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using Xunit;
@@ -35,5 +36,33 @@ namespace WireMock.Net.Tests
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(0.0);
}
[Fact]
public void Request_WithClientIP_WildcardMatcher()
{
// given
var spec = Request.Create().WithClientIP(new WildcardMatcher("127.0.0.2"));
// when
var request = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.2");
// then
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithClientIP_Func()
{
// given
var spec = Request.Create().WithClientIP(c => c.Contains("."));
// when
var request = new RequestMessage(new Uri("http://localhost"), "GET", "127.0.0.2");
// then
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
}
}

View File

@@ -1,5 +1,6 @@
using System;
using NFluent;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.RequestBuilders;
using Xunit;
@@ -25,10 +26,24 @@ namespace WireMock.Net.Tests
}
[Fact]
public void Request_WithUrlExact()
public void Request_WithUrl_WildcardMatcher()
{
// given
var spec = Request.Create().WithUrl("http://localhost/foo");
var spec = Request.Create().WithUrl(new WildcardMatcher("*/foo"));
// when
var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", ClientIp);
// then
var requestMatchResult = new RequestMatchResult();
Check.That(spec.GetMatchingScore(request, requestMatchResult)).IsEqualTo(1.0);
}
[Fact]
public void Request_WithUrl_Func()
{
// given
var spec = Request.Create().WithUrl(url => url.Contains("foo"));
// when
var request = new RequestMessage(new Uri("http://localhost/foo"), "blabla", ClientIp);

View File

@@ -0,0 +1,29 @@
using System;
using System.Threading.Tasks;
using NFluent;
using WireMock.ResponseBuilders;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilderTests
{
public class ResponseCreateTests
{
private const string ClientIp = "::1";
[Fact]
public async Task Response_Create()
{
// Assign
var responseMessage = new ResponseMessage { StatusCode = 500 };
var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp);
var response = Response.Create(() => responseMessage);
// Act
var providedResponse = await response.ProvideResponseAsync(request);
// Assert
Check.That(providedResponse).Equals(responseMessage);
}
}
}

View File

@@ -2,16 +2,41 @@
using System.Collections.Generic;
using System.Text;
using System.Threading.Tasks;
using Newtonsoft.Json;
using NFluent;
using WireMock.ResponseBuilders;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests
namespace WireMock.Net.Tests.ResponseBuilderTests
{
public class ResponseWithBodyHandlebarsTests
{
private const string ClientIp = "::1";
[Fact]
public async Task Response_ProvideResponse_Handlebars_WithBodyAsJson()
{
// given
string jsonString = "{ \"things\": [ { \"name\": \"RequiredThing\" }, { \"name\": \"Wiremock\" } ] }";
var bodyData = new BodyData
{
BodyAsJson = JsonConvert.DeserializeObject(jsonString),
Encoding = Encoding.UTF8
};
var request = new RequestMessage(new Uri("http://localhost/foo"), "POST", ClientIp, bodyData);
var response = Response.Create()
.WithBodyAsJson(new { x = "test {{request.url}}" })
.WithTransformer();
// act
var responseMessage = await response.ProvideResponseAsync(request);
// then
Check.That(JsonConvert.SerializeObject(responseMessage.BodyAsJson)).Equals("{\"x\":\"test http://localhost/foo\"}");
}
[Fact]
public async Task Response_ProvideResponse_Handlebars_UrlPathVerb()
{

View File

@@ -5,7 +5,7 @@ using NFluent;
using WireMock.ResponseBuilders;
using Xunit;
namespace WireMock.Net.Tests
namespace WireMock.Net.Tests.ResponseBuilderTests
{
public class ResponseWithBodyTests
{
@@ -86,5 +86,59 @@ namespace WireMock.Net.Tests
Check.That(responseMessage.BodyAsJson).Equals(x);
Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII);
}
[Fact]
public async Task Response_ProvideResponse_WithBody_String_SameAsSource_Encoding()
{
// Assign
var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp);
var response = Response.Create().WithBody("r", BodyDestinationFormat.SameAsSource, Encoding.ASCII);
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.BodyAsBytes).IsNull();
Check.That(responseMessage.BodyAsJson).IsNull();
Check.That(responseMessage.Body).Equals("r");
Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII);
}
[Fact]
public async Task Response_ProvideResponse_WithBody_String_Bytes_Encoding()
{
// Assign
var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp);
var response = Response.Create().WithBody("r", BodyDestinationFormat.Bytes, Encoding.ASCII);
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).IsNull();
Check.That(responseMessage.BodyAsJson).IsNull();
Check.That(responseMessage.BodyAsBytes).IsNotNull();
Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII);
}
[Fact]
public async Task Response_ProvideResponse_WithBody_String_Json_Encoding()
{
// Assign
var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp);
var response = Response.Create().WithBody("{ \"value\": 42 }", BodyDestinationFormat.Json, Encoding.ASCII);
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Body).IsNull();
Check.That(responseMessage.BodyAsBytes).IsNull();
Check.That(((dynamic) responseMessage.BodyAsJson).value).Equals(42);
Check.That(responseMessage.BodyEncoding).Equals(Encoding.ASCII);
}
}
}

View File

@@ -0,0 +1,60 @@
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
using NFluent;
using WireMock.ResponseBuilders;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilderTests
{
public class ResponseWithHeadersTests
{
private const string ClientIp = "::1";
[Fact]
public async Task Response_ProvideResponse_WithHeaders_SingleValue()
{
// Assign
var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp);
var headers = new Dictionary<string, string> { { "h", "x" } };
var response = Response.Create().WithHeaders(headers);
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Headers["h"]).ContainsExactly("x");
}
[Fact]
public async Task Response_ProvideResponse_WithHeaders_MultipleValues()
{
// Assign
var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp);
var headers = new Dictionary<string, string[]> { { "h", new[] { "x" } } };
var response = Response.Create().WithHeaders(headers);
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Headers["h"]).ContainsExactly("x");
}
[Fact]
public async Task Response_ProvideResponse_WithHeaders_WiremockList()
{
// Assign
var request = new RequestMessage(new Uri("http://localhost"), "GET", ClientIp);
var headers = new Dictionary<string, WireMockList<string>> { { "h", new WireMockList<string>("x") } };
var response = Response.Create().WithHeaders(headers);
// Act
var responseMessage = await response.ProvideResponseAsync(request);
// Assert
Check.That(responseMessage.Headers["h"]).ContainsExactly("x");
}
}
}

Some files were not shown because too many files have changed in this diff Show More