Fix WithBody when using Pact and added more nullable annotations (#783)

* More nullable annotations

* .

* .

* FIX

* pact

* .

* p

* xxx

* ...

* auth

* array

* ...
This commit is contained in:
Stef Heyenrath
2022-08-11 10:57:33 +02:00
committed by GitHub
parent b1af37f044
commit d2a1d0f069
87 changed files with 2578 additions and 2455 deletions
+1
View File
@@ -25,6 +25,7 @@
<s:Boolean x:Key="/Default/UserDictionary/Words/=Victoor/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Victoor/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhook/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Webhook/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhooks/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Webhooks/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=wiremock/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=wiremockserver/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=wiremockserver/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=xunit/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=xunit/@EntryIndexedValue">True</s:Boolean>
</wpf:ResourceDictionary> </wpf:ResourceDictionary>
@@ -1,24 +1,23 @@
namespace WireMock.Admin.Mappings namespace WireMock.Admin.Mappings;
/// <summary>
/// WebProxy settings
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebProxyModel
{ {
/// <summary>
/// WebProxy settings
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebProxyModel
{
/// <summary> /// <summary>
/// A string instance that contains the address of the proxy server. /// A string instance that contains the address of the proxy server.
/// </summary> /// </summary>
public string Address { get; set; } public string Address { get; set; } = null!;
/// <summary> /// <summary>
/// The user name associated with the credentials. /// The user name associated with the credentials. [optional]
/// </summary> /// </summary>
public string UserName { get; set; } public string? UserName { get; set; }
/// <summary> /// <summary>
/// The password for the user name associated with the credentials. /// The password for the user name associated with the credentials. [optional]
/// </summary> /// </summary>
public string Password { get; set; } public string? Password { get; set; }
}
} }
@@ -1,14 +1,13 @@
using System.Collections.Generic; using System.Collections.Generic;
using WireMock.Types;
namespace WireMock.Admin.Mappings namespace WireMock.Admin.Mappings;
/// <summary>
/// RequestModel
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebhookRequestModel
{ {
/// <summary>
/// RequestModel
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebhookRequestModel
{
/// <summary> /// <summary>
/// Gets or sets the Url. /// Gets or sets the Url.
/// </summary> /// </summary>
@@ -42,11 +41,10 @@ namespace WireMock.Admin.Mappings
/// <summary> /// <summary>
/// Gets the type of the transformer. /// Gets the type of the transformer.
/// </summary> /// </summary>
public string TransformerType { get; set; } public string? TransformerType { get; set; }
/// <summary> /// <summary>
/// The ReplaceNodeOptions to use when transforming a JSON node. /// The ReplaceNodeOptions to use when transforming a JSON node.
/// </summary> /// </summary>
public string TransformerReplaceNodeOptions { get; set; } public string? TransformerReplaceNodeOptions { get; set; }
}
} }
@@ -63,12 +63,12 @@ public interface IRequestMessage
/// <summary> /// <summary>
/// Gets the headers. /// Gets the headers.
/// </summary> /// </summary>
IDictionary<string, WireMockList<string>> Headers { get; } IDictionary<string, WireMockList<string>>? Headers { get; }
/// <summary> /// <summary>
/// Gets the cookies. /// Gets the cookies.
/// </summary> /// </summary>
IDictionary<string, string> Cookies { get; } IDictionary<string, string>? Cookies { get; }
/// <summary> /// <summary>
/// Gets the query. /// Gets the query.
@@ -3,27 +3,27 @@ using WireMock.ResponseBuilders;
using WireMock.Types; using WireMock.Types;
using WireMock.Util; using WireMock.Util;
namespace WireMock namespace WireMock;
/// <summary>
/// IResponseMessage
/// </summary>
public interface IResponseMessage
{ {
/// <summary>
/// IResponseMessage
/// </summary>
public interface IResponseMessage
{
/// <summary> /// <summary>
/// The Body. /// The Body.
/// </summary> /// </summary>
IBodyData? BodyData { get; } IBodyData? BodyData { get; }
/// <summary> /// <summary>
/// Gets the body destination (SameAsSource, String or Bytes). /// Gets the body destination (Null, SameAsSource, String or Bytes).
/// </summary> /// </summary>
string BodyDestination { get; } string? BodyDestination { get; }
/// <summary> /// <summary>
/// Gets or sets the body. /// Gets or sets the body.
/// </summary> /// </summary>
string BodyOriginal { get; } string? BodyOriginal { get; }
/// <summary> /// <summary>
/// Gets the Fault percentage. /// Gets the Fault percentage.
@@ -43,7 +43,7 @@ namespace WireMock
/// <summary> /// <summary>
/// Gets or sets the status code. /// Gets or sets the status code.
/// </summary> /// </summary>
object StatusCode { get; } object? StatusCode { get; }
/// <summary> /// <summary>
/// Adds the header. /// Adds the header.
@@ -58,5 +58,4 @@ namespace WireMock
/// <param name="name">The name.</param> /// <param name="name">The name.</param>
/// <param name="values">The values.</param> /// <param name="values">The values.</param>
void AddHeader(string name, params string[] values); void AddHeader(string name, params string[] values);
}
} }
@@ -1,13 +1,13 @@
using System; using System;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
namespace WireMock.Logging namespace WireMock.Logging;
/// <summary>
/// ILogEntry
/// </summary>
public interface ILogEntry
{ {
/// <summary>
/// ILogEntry
/// </summary>
public interface ILogEntry
{
/// <summary> /// <summary>
/// Gets the unique identifier. /// Gets the unique identifier.
/// </summary> /// </summary>
@@ -21,7 +21,7 @@ namespace WireMock.Logging
/// <summary> /// <summary>
/// Gets the mapping unique title. /// Gets the mapping unique title.
/// </summary> /// </summary>
string MappingTitle { get; } string? MappingTitle { get; }
/// <summary> /// <summary>
/// Gets the partial mapping unique identifier. /// Gets the partial mapping unique identifier.
@@ -31,7 +31,7 @@ namespace WireMock.Logging
/// <summary> /// <summary>
/// Gets the partial mapping unique title. /// Gets the partial mapping unique title.
/// </summary> /// </summary>
string PartialMappingTitle { get; } string? PartialMappingTitle { get; }
/// <summary> /// <summary>
/// Gets the partial match result. /// Gets the partial match result.
@@ -52,5 +52,4 @@ namespace WireMock.Logging
/// Gets the response message. /// Gets the response message.
/// </summary> /// </summary>
IResponseMessage ResponseMessage { get; } IResponseMessage ResponseMessage { get; }
}
} }
@@ -1,13 +1,12 @@
namespace WireMock.Models namespace WireMock.Models;
/// <summary>
/// IWebhook
/// </summary>
public interface IWebhook
{ {
/// <summary>
/// IWebhook
/// </summary>
public interface IWebhook
{
/// <summary> /// <summary>
/// Request /// Request
/// </summary> /// </summary>
IWebhookRequest Request { get; set; } IWebhookRequest Request { get; set; }
}
} }
@@ -59,7 +59,7 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher
MatchOperator = matchOperator; MatchOperator = matchOperator;
} }
public double IsMatch(string input) public double IsMatch(string? input)
{ {
return IsMatchInternal(input); return IsMatchInternal(input);
} }
@@ -1,4 +1,5 @@
#if !NETSTANDARD1_3 #if !NETSTANDARD1_3
using System;
using System.Globalization; using System.Globalization;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
@@ -6,17 +7,18 @@ using AnyOfTypes;
using Microsoft.IdentityModel.Protocols; using Microsoft.IdentityModel.Protocols;
using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Microsoft.IdentityModel.Protocols.OpenIdConnect;
using Microsoft.IdentityModel.Tokens; using Microsoft.IdentityModel.Tokens;
using Stef.Validation;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.Models; using WireMock.Models;
namespace WireMock.Authentication namespace WireMock.Authentication;
/// <summary>
/// https://www.c-sharpcorner.com/article/how-to-validate-azure-ad-token-using-console-application/
/// https://stackoverflow.com/questions/38684865/validation-of-an-azure-ad-bearer-token-in-a-console-application
/// </summary>
internal class AzureADAuthenticationMatcher : IStringMatcher
{ {
/// <summary>
/// https://www.c-sharpcorner.com/article/how-to-validate-azure-ad-token-using-console-application/
/// https://stackoverflow.com/questions/38684865/validation-of-an-azure-ad-bearer-token-in-a-console-application
/// </summary>
internal class AzureADAuthenticationMatcher : IStringMatcher
{
private const string BearerPrefix = "Bearer "; private const string BearerPrefix = "Bearer ";
private readonly string _audience; private readonly string _audience;
@@ -24,8 +26,8 @@ namespace WireMock.Authentication
public AzureADAuthenticationMatcher(string tenant, string audience) public AzureADAuthenticationMatcher(string tenant, string audience)
{ {
_audience = audience; _audience = Guard.NotNullOrEmpty(audience);
_stsDiscoveryEndpoint = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/.well-known/openid-configuration", tenant); _stsDiscoveryEndpoint = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/.well-known/openid-configuration", Guard.NotNullOrEmpty(tenant));
} }
public string Name => nameof(AzureADAuthenticationMatcher); public string Name => nameof(AzureADAuthenticationMatcher);
@@ -36,13 +38,18 @@ namespace WireMock.Authentication
public AnyOf<string, StringPattern>[] GetPatterns() public AnyOf<string, StringPattern>[] GetPatterns()
{ {
return new AnyOf<string, StringPattern>[0]; return EmptyArray<AnyOf<string, StringPattern>>.Value;
} }
public MatchOperator MatchOperator { get; } = MatchOperator.Or; public MatchOperator MatchOperator { get; } = MatchOperator.Or;
public double IsMatch(string input) public double IsMatch(string? input)
{ {
if (string.IsNullOrEmpty(input))
{
return MatchScores.Mismatch;
}
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase); var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase);
try try
@@ -68,6 +75,5 @@ namespace WireMock.Authentication
return MatchScores.Mismatch; return MatchScores.Mismatch;
} }
} }
}
} }
#endif #endif
@@ -2,10 +2,10 @@ using System;
using System.Text; using System.Text;
using WireMock.Matchers; using WireMock.Matchers;
namespace WireMock.Authentication namespace WireMock.Authentication;
internal class BasicAuthenticationMatcher : RegexMatcher
{ {
internal class BasicAuthenticationMatcher : RegexMatcher
{
public BasicAuthenticationMatcher(string username, string password) : base(BuildPattern(username, password)) public BasicAuthenticationMatcher(string username, string password) : base(BuildPattern(username, password))
{ {
} }
@@ -16,5 +16,4 @@ namespace WireMock.Authentication
{ {
return "^(?i)BASIC " + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password)) + "$"; return "^(?i)BASIC " + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password)) + "$";
} }
}
} }
@@ -0,0 +1,11 @@
// ReSharper disable once CheckNamespace
namespace System;
internal static class EmptyArray<T>
{
#if NET451 || NET452
public static readonly T[] Value = new T[0];
#else
public static readonly T[] Value = Array.Empty<T>();
#endif
}
+6 -8
View File
@@ -1,13 +1,12 @@
#if NETSTANDARD1_3 #if NETSTANDARD1_3
using System;
using System.Net;
namespace System.Net // ReSharper disable once CheckNamespace
namespace System.Net;
internal class WebProxy : IWebProxy
{ {
internal class WebProxy : IWebProxy
{
private readonly string _proxy; private readonly string _proxy;
public ICredentials Credentials { get; set; } public ICredentials? Credentials { get; set; }
public WebProxy(string proxy) public WebProxy(string proxy)
{ {
@@ -23,6 +22,5 @@ namespace System.Net
{ {
return true; return true;
} }
}
} }
#endif #endif
@@ -1,26 +1,24 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using AnyOfTypes; using AnyOfTypes;
using JetBrains.Annotations;
using WireMock.Models; using WireMock.Models;
namespace WireMock.Extensions namespace WireMock.Extensions;
internal static class AnyOfExtensions
{ {
internal static class AnyOfExtensions public static string GetPattern(this AnyOf<string, StringPattern> value)
{
public static string GetPattern([NotNull] this AnyOf<string, StringPattern> value)
{ {
return value.IsFirst ? value.First : value.Second.Pattern; return value.IsFirst ? value.First : value.Second.Pattern;
} }
public static AnyOf<string, StringPattern>[] ToAnyOfPatterns([NotNull] this IEnumerable<string> patterns) public static AnyOf<string, StringPattern>[] ToAnyOfPatterns(this IEnumerable<string> patterns)
{ {
return patterns.Select(p => p.ToAnyOfPattern()).ToArray(); return patterns.Select(p => p.ToAnyOfPattern()).ToArray();
} }
public static AnyOf<string, StringPattern> ToAnyOfPattern([CanBeNull] this string pattern) public static AnyOf<string, StringPattern> ToAnyOfPattern(this string pattern)
{ {
return new AnyOf<string, StringPattern>(pattern); return new AnyOf<string, StringPattern>(pattern);
} }
}
} }
@@ -1,21 +1,20 @@
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using JetBrains.Annotations;
using Stef.Validation; using Stef.Validation;
namespace WireMock.Http namespace WireMock.Http;
internal static class ByteArrayContentHelper
{ {
internal static class ByteArrayContentHelper
{
/// <summary> /// <summary>
/// Creates a ByteArrayContent object. /// Creates a ByteArrayContent object.
/// </summary> /// </summary>
/// <param name="content">The byte[] content (cannot be null)</param> /// <param name="content">The byte[] content (cannot be null)</param>
/// <param name="contentType">The ContentType (can be null)</param> /// <param name="contentType">The ContentType (can be null)</param>
/// <returns>ByteArrayContent</returns> /// <returns>ByteArrayContent</returns>
internal static ByteArrayContent Create([NotNull] byte[] content, [CanBeNull] MediaTypeHeaderValue contentType) internal static ByteArrayContent Create(byte[] content, MediaTypeHeaderValue? contentType)
{ {
Guard.NotNull(content, nameof(content)); Guard.NotNull(content);
var byteContent = new ByteArrayContent(content); var byteContent = new ByteArrayContent(content);
if (contentType != null) if (contentType != null)
@@ -26,5 +25,4 @@ namespace WireMock.Http
return byteContent; return byteContent;
} }
}
} }
@@ -1,17 +1,17 @@
// Licensed to the .NET Foundation under one or more agreements. // Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license. // The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information. // See the LICENSE file in the project root for more information.
using System; using System;
using System.Linq; using System.Linq;
namespace WireMock.Http namespace WireMock.Http;
/// <summary>
/// Copied from https://raw.githubusercontent.com/dotnet/corefx/master/src/Common/src/System/Net/HttpKnownHeaderNames.cs
/// </summary>
internal static class HttpKnownHeaderNames
{ {
/// <summary>
/// Copied from https://raw.githubusercontent.com/dotnet/corefx/master/src/Common/src/System/Net/HttpKnownHeaderNames.cs
/// </summary>
internal static class HttpKnownHeaderNames
{
// https://docs.microsoft.com/en-us/dotnet/api/system.net.webheadercollection.isrestricted // https://docs.microsoft.com/en-us/dotnet/api/system.net.webheadercollection.isrestricted
private static readonly string[] RestrictedResponseHeaders = private static readonly string[] RestrictedResponseHeaders =
{ {
@@ -118,5 +118,4 @@ namespace WireMock.Http
public const string XPoweredBy = "X-Powered-By"; public const string XPoweredBy = "X-Powered-By";
public const string XRequestID = "X-Request-ID"; public const string XRequestID = "X-Request-ID";
public const string XUACompatible = "X-UA-Compatible"; public const string XUACompatible = "X-UA-Compatible";
}
} }
@@ -3,23 +3,22 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using JetBrains.Annotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using WireMock.Types;
using Stef.Validation; using Stef.Validation;
using WireMock.Types;
namespace WireMock.Http namespace WireMock.Http;
internal static class HttpRequestMessageHelper
{ {
internal static class HttpRequestMessageHelper internal static HttpRequestMessage Create(IRequestMessage requestMessage, string url)
{ {
internal static HttpRequestMessage Create([NotNull] IRequestMessage requestMessage, [NotNull] string url) Guard.NotNull(requestMessage);
{ Guard.NotNullOrEmpty(url);
Guard.NotNull(requestMessage, nameof(requestMessage));
Guard.NotNullOrEmpty(url, nameof(url));
var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url); var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url);
MediaTypeHeaderValue contentType = null; MediaTypeHeaderValue? contentType = null;
if (requestMessage.Headers != null && requestMessage.Headers.ContainsKey(HttpKnownHeaderNames.ContentType)) if (requestMessage.Headers != null && requestMessage.Headers.ContainsKey(HttpKnownHeaderNames.ContentType))
{ {
var value = requestMessage.Headers[HttpKnownHeaderNames.ContentType].FirstOrDefault(); var value = requestMessage.Headers[HttpKnownHeaderNames.ContentType].FirstOrDefault();
@@ -87,5 +86,4 @@ namespace WireMock.Http
return httpRequestMessage; return httpRequestMessage;
} }
}
} }
+6 -7
View File
@@ -1,10 +1,10 @@
namespace WireMock.Http namespace WireMock.Http;
/// <summary>
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
/// </summary>
internal static class HttpRequestMethods
{ {
/// <summary>
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
/// </summary>
internal static class HttpRequestMethods
{
public const string CONNECT = "CONNECT"; public const string CONNECT = "CONNECT";
public const string DELETE = "DELETE"; public const string DELETE = "DELETE";
public const string GET = "GET"; public const string GET = "GET";
@@ -14,5 +14,4 @@
public const string POST = "POST"; public const string POST = "POST";
public const string PUT = "PUT"; public const string PUT = "PUT";
public const string TRACE = "TRACE"; public const string TRACE = "TRACE";
}
} }
+6 -8
View File
@@ -1,25 +1,23 @@
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using JetBrains.Annotations;
using Stef.Validation; using Stef.Validation;
namespace WireMock.Http namespace WireMock.Http;
internal static class StringContentHelper
{ {
internal static class StringContentHelper
{
/// <summary> /// <summary>
/// Creates a StringContent object. /// Creates a StringContent object.
/// </summary> /// </summary>
/// <param name="content">The string content (cannot be null)</param> /// <param name="content">The string content (cannot be null)</param>
/// <param name="contentType">The ContentType (can be null)</param> /// <param name="contentType">The ContentType (can be null)</param>
/// <returns>StringContent</returns> /// <returns>StringContent</returns>
internal static StringContent Create([NotNull] string content, [CanBeNull] MediaTypeHeaderValue contentType) internal static StringContent Create(string content, MediaTypeHeaderValue? contentType)
{ {
Guard.NotNull(content, nameof(content)); Guard.NotNull(content);
var stringContent = new StringContent(content); var stringContent = new StringContent(content);
stringContent.Headers.ContentType = contentType; stringContent.Headers.ContentType = contentType;
return stringContent; return stringContent;
} }
}
} }
+5 -7
View File
@@ -3,7 +3,7 @@ using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using Stef.Validation;
using WireMock.Models; using WireMock.Models;
using WireMock.Settings; using WireMock.Settings;
using WireMock.Transformers; using WireMock.Transformers;
@@ -11,19 +11,18 @@ using WireMock.Transformers.Handlebars;
using WireMock.Transformers.Scriban; using WireMock.Transformers.Scriban;
using WireMock.Types; using WireMock.Types;
using WireMock.Util; using WireMock.Util;
using Stef.Validation;
namespace WireMock.Http namespace WireMock.Http;
internal class WebhookSender
{ {
internal class WebhookSender
{
private const string ClientIp = "::1"; private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings; private readonly WireMockServerSettings _settings;
public WebhookSender(WireMockServerSettings settings) public WebhookSender(WireMockServerSettings settings)
{ {
_settings = settings ?? throw new ArgumentNullException(nameof(settings)); _settings = Guard.NotNull(settings);
} }
public Task<HttpResponseMessage> SendAsync(HttpClient client, IWebhookRequest request, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage) public Task<HttpResponseMessage> SendAsync(HttpClient client, IWebhookRequest request, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage)
@@ -81,5 +80,4 @@ namespace WireMock.Http
// Call the URL // Call the URL
return client.SendAsync(httpRequestMessage); return client.SendAsync(httpRequestMessage);
} }
}
} }
@@ -2,10 +2,10 @@ using System;
using System.IO; using System.IO;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
namespace WireMock.HttpsCertificate namespace WireMock.HttpsCertificate;
internal static class CertificateLoader
{ {
internal static class CertificateLoader
{
/// <summary> /// <summary>
/// Used by the WireMock.Net server /// Used by the WireMock.Net server
/// </summary> /// </summary>
@@ -101,5 +101,4 @@ namespace WireMock.HttpsCertificate
#endif #endif
} }
} }
}
} }
@@ -1,13 +1,13 @@
using System; using System;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
namespace WireMock.HttpsCertificate namespace WireMock.HttpsCertificate;
/// <summary>
/// Only used for NetStandard 1.3
/// </summary>
internal static class PublicCertificateHelper
{ {
/// <summary>
/// Only used for NetStandard 1.3
/// </summary>
internal static class PublicCertificateHelper
{
// 1] Generate using https://www.pluralsight.com/blog/software-development/selfcert-create-a-self-signed-certificate-interactively-gui-or-programmatically-in-net // 1] Generate using https://www.pluralsight.com/blog/software-development/selfcert-create-a-self-signed-certificate-interactively-gui-or-programmatically-in-net
// 2] Converted to Base64 // 2] Converted to Base64
private const string Data = @"MIIQMgIBAzCCD+4GCSqGSIb3DQEHAaCCD98Egg/bMIIP1zCCCogGCSqGSIb3DQEHAaCCCnkEggp1 private const string Data = @"MIIQMgIBAzCCD+4GCSqGSIb3DQEHAaCCD98Egg/bMIIP1zCCCogGCSqGSIb3DQEHAaCCCnkEggp1
@@ -90,5 +90,4 @@ wTM1Z+CJZG9xAcf1zAVGl4ggYyYEFGBFyJ8VBwijS2zy1qwN1WYGtcWoAgIH0A==
byte[] data = Convert.FromBase64String(Data); byte[] data = Convert.FromBase64String(Data);
return new X509Certificate2(data); return new X509Certificate2(data);
} }
}
} }
+1 -1
View File
@@ -117,7 +117,7 @@ public interface IMapping
/// </summary> /// </summary>
/// <param name="requestMessage">The request message.</param> /// <param name="requestMessage">The request message.</param>
/// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns> /// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns>
Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage); Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage);
/// <summary> /// <summary>
/// Gets the RequestMatchResult based on the RequestMessage. /// Gets the RequestMatchResult based on the RequestMessage.
+9 -10
View File
@@ -1,13 +1,13 @@
using System; using System;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
namespace WireMock.Logging namespace WireMock.Logging;
/// <summary>
/// LogEntry
/// </summary>
public class LogEntry : ILogEntry
{ {
/// <summary>
/// LogEntry
/// </summary>
public class LogEntry : ILogEntry
{
/// <inheritdoc cref="ILogEntry.Guid" /> /// <inheritdoc cref="ILogEntry.Guid" />
public Guid Guid { get; set; } public Guid Guid { get; set; }
@@ -24,15 +24,14 @@ namespace WireMock.Logging
public Guid? MappingGuid { get; set; } public Guid? MappingGuid { get; set; }
/// <inheritdoc cref="ILogEntry.MappingTitle" /> /// <inheritdoc cref="ILogEntry.MappingTitle" />
public string MappingTitle { get; set; } public string? MappingTitle { get; set; }
/// <inheritdoc cref="ILogEntry.PartialMappingGuid" /> /// <inheritdoc cref="ILogEntry.PartialMappingGuid" />
public Guid? PartialMappingGuid { get; set; } public Guid? PartialMappingGuid { get; set; }
/// <inheritdoc cref="ILogEntry.PartialMappingTitle" /> /// <inheritdoc cref="ILogEntry.PartialMappingTitle" />
public string PartialMappingTitle { get; set; } public string? PartialMappingTitle { get; set; }
/// <inheritdoc cref="ILogEntry.PartialMatchResult" /> /// <inheritdoc cref="ILogEntry.PartialMatchResult" />
public IRequestMatchResult PartialMatchResult { get; set; } public IRequestMatchResult PartialMatchResult { get; set; }
}
} }
+1 -1
View File
@@ -116,7 +116,7 @@ public class Mapping : IMapping
} }
/// <inheritdoc cref="IMapping.ProvideResponseAsync" /> /// <inheritdoc cref="IMapping.ProvideResponseAsync" />
public Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage) public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
{ {
return Provider.ProvideResponseAsync(requestMessage, Settings); return Provider.ProvideResponseAsync(requestMessage, Settings);
} }
@@ -18,7 +18,7 @@ public class ContentTypeMatcher : WildcardMatcher
/// </summary> /// </summary>
/// <param name="pattern">The pattern.</param> /// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param> /// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher([NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase) public ContentTypeMatcher(AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
{ {
} }
@@ -28,7 +28,7 @@ public class ContentTypeMatcher : WildcardMatcher
/// <param name="matchBehaviour">The match behaviour.</param> /// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param> /// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param> /// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase) public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
{ {
} }
@@ -57,7 +57,7 @@ public class ContentTypeMatcher : WildcardMatcher
/// <inheritdoc cref="RegexMatcher.IsMatch"/> /// <inheritdoc cref="RegexMatcher.IsMatch"/>
public override double IsMatch(string? input) public override double IsMatch(string? input)
{ {
if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out MediaTypeHeaderValue contentType)) if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out var contentType))
{ {
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch); return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
} }
@@ -1,11 +1,10 @@
namespace WireMock.Matchers namespace WireMock.Matchers;
/// <summary>
/// CSharpCode / CS-Script Matcher
/// </summary>
/// <inheritdoc cref="IObjectMatcher"/>
/// <inheritdoc cref="IStringMatcher"/>
public interface ICSharpCodeMatcher : IObjectMatcher, IStringMatcher
{ {
/// <summary>
/// CSharpCode / CS-Script Matcher
/// </summary>
/// <inheritdoc cref="IObjectMatcher"/>
/// <inheritdoc cref="IStringMatcher"/>
public interface ICSharpCodeMatcher : IObjectMatcher, IStringMatcher
{
}
} }
@@ -1,14 +1,13 @@
namespace WireMock.Matchers namespace WireMock.Matchers;
/// <summary>
/// IIgnoreCaseMatcher
/// </summary>
/// <inheritdoc cref="IMatcher"/>
public interface IIgnoreCaseMatcher : IMatcher
{ {
/// <summary>
/// IIgnoreCaseMatcher
/// </summary>
/// <inheritdoc cref="IMatcher"/>
public interface IIgnoreCaseMatcher : IMatcher
{
/// <summary> /// <summary>
/// Ignore the case from the pattern. /// Ignore the case from the pattern.
/// </summary> /// </summary>
bool IgnoreCase { get; } bool IgnoreCase { get; }
}
} }
+6 -7
View File
@@ -1,10 +1,10 @@
namespace WireMock.Matchers namespace WireMock.Matchers;
/// <summary>
/// IMatcher
/// </summary>
public interface IMatcher
{ {
/// <summary>
/// IMatcher
/// </summary>
public interface IMatcher
{
/// <summary> /// <summary>
/// Gets the name. /// Gets the name.
/// </summary> /// </summary>
@@ -19,5 +19,4 @@
/// Should this matcher throw an exception? /// Should this matcher throw an exception?
/// </summary> /// </summary>
bool ThrowException { get; } bool ThrowException { get; }
}
} }
+6 -7
View File
@@ -1,15 +1,14 @@
namespace WireMock.Matchers namespace WireMock.Matchers;
/// <summary>
/// IObjectMatcher
/// </summary>
public interface IObjectMatcher : IMatcher
{ {
/// <summary>
/// IObjectMatcher
/// </summary>
public interface IObjectMatcher : IMatcher
{
/// <summary> /// <summary>
/// Determines whether the specified input is match. /// Determines whether the specified input is match.
/// </summary> /// </summary>
/// <param name="input">The input.</param> /// <param name="input">The input.</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns> /// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
double IsMatch(object? input); double IsMatch(object? input);
}
} }
+7 -8
View File
@@ -1,15 +1,14 @@
namespace WireMock.Matchers namespace WireMock.Matchers;
/// <summary>
/// IValueMatcher
/// </summary>
/// <seealso cref="IObjectMatcher" />
public interface IValueMatcher : IObjectMatcher
{ {
/// <summary>
/// IValueMatcher
/// </summary>
/// <seealso cref="IObjectMatcher" />
public interface IValueMatcher : IObjectMatcher
{
/// <summary> /// <summary>
/// Gets the value (can be a string or an object). /// Gets the value (can be a string or an object).
/// </summary> /// </summary>
/// <returns>Value</returns> /// <returns>Value</returns>
object Value { get; } object Value { get; }
}
} }
+6 -7
View File
@@ -6,13 +6,13 @@ using Stef.Validation;
using WireMock.Extensions; using WireMock.Extensions;
using WireMock.Models; using WireMock.Models;
namespace WireMock.Matchers namespace WireMock.Matchers;
/// <summary>
/// http://jmespath.org/
/// </summary>
public class JmesPathMatcher : IStringMatcher, IObjectMatcher
{ {
/// <summary>
/// http://jmespath.org/
/// </summary>
public class JmesPathMatcher : IStringMatcher, IObjectMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns; private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc cref="IMatcher.MatchBehaviour"/> /// <inheritdoc cref="IMatcher.MatchBehaviour"/>
@@ -116,5 +116,4 @@ namespace WireMock.Matchers
/// <inheritdoc cref="IMatcher.Name"/> /// <inheritdoc cref="IMatcher.Name"/>
public string Name => "JmesPathMatcher"; public string Name => "JmesPathMatcher";
}
} }
+1 -1
View File
@@ -119,7 +119,7 @@ public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher
return tokenValue; return tokenValue;
case string stringValue: case string stringValue:
return JsonUtils.Parse(stringValue)!; return JsonUtils.Parse(stringValue);
case IEnumerable enumerableValue: case IEnumerable enumerableValue:
return JArray.FromObject(enumerableValue); return JArray.FromObject(enumerableValue);
+8 -4
View File
@@ -1,3 +1,4 @@
using System;
using System.Linq; using System.Linq;
using System.Linq.Dynamic.Core; using System.Linq.Dynamic.Core;
using AnyOfTypes; using AnyOfTypes;
@@ -68,7 +69,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
} }
/// <inheritdoc cref="IStringMatcher.IsMatch"/> /// <inheritdoc cref="IStringMatcher.IsMatch"/>
public double IsMatch(string input) public double IsMatch(string? input)
{ {
double match = MatchScores.Mismatch; double match = MatchScores.Mismatch;
@@ -94,7 +95,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
} }
/// <inheritdoc cref="IObjectMatcher.IsMatch"/> /// <inheritdoc cref="IObjectMatcher.IsMatch"/>
public double IsMatch(object input) public double IsMatch(object? input)
{ {
double match = MatchScores.Mismatch; double match = MatchScores.Mismatch;
@@ -105,9 +106,12 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
value = valueAsJObject; value = valueAsJObject;
break; break;
default: case { } valueAsObject:
value = JObject.FromObject(input); value = JObject.FromObject(valueAsObject);
break; break;
default:
return MatchScores.Mismatch;
} }
// Convert a single object to a Queryable JObject-list with 1 entry. // Convert a single object to a Queryable JObject-list with 1 entry.
+6 -7
View File
@@ -1,10 +1,10 @@
namespace WireMock.Matchers namespace WireMock.Matchers;
/// <summary>
/// MatchBehaviour
/// </summary>
public enum MatchBehaviour
{ {
/// <summary>
/// MatchBehaviour
/// </summary>
public enum MatchBehaviour
{
/// <summary> /// <summary>
/// Accept on match (default) /// Accept on match (default)
/// </summary> /// </summary>
@@ -14,5 +14,4 @@
/// Reject on match /// Reject on match
/// </summary> /// </summary>
RejectOnMatch RejectOnMatch
}
} }
@@ -1,7 +1,7 @@
namespace WireMock.Matchers namespace WireMock.Matchers;
internal static class MatchBehaviourHelper
{ {
internal static class MatchBehaviourHelper
{
/// <summary> /// <summary>
/// Converts the specified match behaviour and match value to a new match value. /// Converts the specified match behaviour and match value to a new match value.
/// ///
@@ -23,5 +23,4 @@
return match <= MatchScores.Tolerance ? MatchScores.Perfect : MatchScores.Mismatch; return match <= MatchScores.Tolerance ? MatchScores.Perfect : MatchScores.Mismatch;
} }
}
} }
@@ -1,10 +1,10 @@
namespace WireMock.Matchers.Request namespace WireMock.Matchers.Request;
/// <summary>
/// CompositeMatcherType
/// </summary>
public enum CompositeMatcherType
{ {
/// <summary>
/// CompositeMatcherType
/// </summary>
public enum CompositeMatcherType
{
/// <summary> /// <summary>
/// And /// And
/// </summary> /// </summary>
@@ -14,5 +14,4 @@
/// Or /// Or
/// </summary> /// </summary>
Or = 1 Or = 1
}
} }
@@ -1,14 +1,14 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace WireMock.Matchers.Request namespace WireMock.Matchers.Request;
/// <summary>
/// RequestMatchResult
/// </summary>
public class RequestMatchResult : IRequestMatchResult
{ {
/// <summary>
/// RequestMatchResult
/// </summary>
public class RequestMatchResult : IRequestMatchResult
{
/// <inheritdoc cref="IRequestMatchResult.TotalScore" /> /// <inheritdoc cref="IRequestMatchResult.TotalScore" />
public double TotalScore => MatchDetails.Sum(md => md.Score); public double TotalScore => MatchDetails.Sum(md => md.Score);
@@ -53,5 +53,4 @@ namespace WireMock.Matchers.Request
// In case the score is equal, prefer the one with the most matchers. // In case the score is equal, prefer the one with the most matchers.
return averageTotalScoreResult == 0 ? compareObj.TotalNumber.CompareTo(TotalNumber) : averageTotalScoreResult; return averageTotalScoreResult == 0 ? compareObj.TotalNumber.CompareTo(TotalNumber) : averageTotalScoreResult;
} }
}
} }
@@ -3,13 +3,13 @@ using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Stef.Validation; using Stef.Validation;
namespace WireMock.Matchers.Request namespace WireMock.Matchers.Request;
/// <summary>
/// The composite request matcher.
/// </summary>
public abstract class RequestMessageCompositeMatcher : IRequestMatcher
{ {
/// <summary>
/// The composite request matcher.
/// </summary>
public abstract class RequestMessageCompositeMatcher : IRequestMatcher
{
private readonly CompositeMatcherType _type; private readonly CompositeMatcherType _type;
/// <summary> /// <summary>
@@ -48,5 +48,4 @@ namespace WireMock.Matchers.Request
return RequestMatchers.Max(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult)); return RequestMatchers.Max(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult));
} }
}
} }
@@ -4,14 +4,14 @@ using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Stef.Validation; using Stef.Validation;
namespace WireMock.Matchers.Request namespace WireMock.Matchers.Request;
/// <summary>
/// The request cookie matcher.
/// </summary>
/// <inheritdoc cref="IRequestMatcher"/>
public class RequestMessageCookieMatcher : IRequestMatcher
{ {
/// <summary>
/// The request cookie matcher.
/// </summary>
/// <inheritdoc cref="IRequestMatcher"/>
public class RequestMessageCookieMatcher : IRequestMatcher
{
private readonly MatchBehaviour _matchBehaviour; private readonly MatchBehaviour _matchBehaviour;
private readonly bool _ignoreCase; private readonly bool _ignoreCase;
@@ -125,5 +125,4 @@ namespace WireMock.Matchers.Request
string value = cookies[Name]; string value = cookies[Name];
return Matchers.Max(m => m.IsMatch(value)); return Matchers.Max(m => m.IsMatch(value));
} }
}
} }
+2 -3
View File
@@ -5,7 +5,6 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
@@ -30,9 +29,9 @@ namespace WireMock.Owin
public bool IsStarted { get; private set; } public bool IsStarted { get; private set; }
public List<string> Urls { get; } = new List<string>(); public List<string> Urls { get; } = new();
public List<int> Ports { get; } = new List<int>(); public List<int> Ports { get; } = new();
public Exception RunningException => _runningException; public Exception RunningException => _runningException;
@@ -71,7 +71,6 @@ namespace WireMock.Owin.Mappers
{ {
bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray(); bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray();
} }
break; break;
default: default:
@@ -80,11 +79,10 @@ namespace WireMock.Owin.Mappers
} }
var statusCodeType = responseMessage.StatusCode?.GetType(); var statusCodeType = responseMessage.StatusCode?.GetType();
switch (statusCodeType) switch (statusCodeType)
{ {
case Type typeAsIntOrEnum when typeAsIntOrEnum == typeof(int) || typeAsIntOrEnum == typeof(int?) || typeAsIntOrEnum.GetTypeInfo().IsEnum: case Type typeAsIntOrEnum when typeAsIntOrEnum == typeof(int) || typeAsIntOrEnum == typeof(int?) || typeAsIntOrEnum.GetTypeInfo().IsEnum:
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode); response.StatusCode = MapStatusCode((int)responseMessage.StatusCode!);
break; break;
case Type typeAsString when typeAsString == typeof(string): case Type typeAsString when typeAsString == typeof(string):
@@ -138,7 +136,7 @@ namespace WireMock.Owin.Mappers
return responseMessage.BodyData.BodyAsBytes; return responseMessage.BodyData.BodyAsBytes;
case BodyType.File: case BodyType.File:
return _options.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile); return _options.FileSystemHandler?.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
} }
return null; return null;
@@ -2,11 +2,11 @@ namespace WireMock.Pact.Models.V2;
public class Interaction public class Interaction
{ {
public string Description { get; set; } = string.Empty; public string? Description { get; set; }
public string ProviderState { get; set; } public string? ProviderState { get; set; }
public PactRequest Request { get; set; } = new PactRequest(); public PactRequest Request { get; set; } = new();
public PactResponse Response { get; set; } = new PactResponse(); public PactResponse Response { get; set; } = new();
} }
+7 -8
View File
@@ -1,14 +1,14 @@
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
namespace WireMock.Plugin namespace WireMock.Plugin;
internal static class PluginLoader
{ {
internal static class PluginLoader private static readonly ConcurrentDictionary<Type, Type> Assemblies = new();
{
private static readonly ConcurrentDictionary<Type, Type> Assemblies = new ConcurrentDictionary<Type, Type>();
public static T Load<T>(params object[] args) where T : class public static T Load<T>(params object[] args) where T : class
{ {
@@ -16,7 +16,7 @@ namespace WireMock.Plugin
{ {
var files = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll"); var files = Directory.GetFiles(Directory.GetCurrentDirectory(), "*.dll");
Type pluginType = null; Type? pluginType = null;
foreach (var file in files) foreach (var file in files)
{ {
try try
@@ -49,9 +49,8 @@ namespace WireMock.Plugin
return (T)Activator.CreateInstance(foundType, args); return (T)Activator.CreateInstance(foundType, args);
} }
private static Type GetImplementationTypeByInterface<T>(Assembly assembly) private static Type? GetImplementationTypeByInterface<T>(Assembly assembly)
{ {
return assembly.GetTypes().FirstOrDefault(t => typeof(T).IsAssignableFrom(t) && !t.GetTypeInfo().IsInterface); return assembly.GetTypes().FirstOrDefault(t => typeof(T).IsAssignableFrom(t) && !t.GetTypeInfo().IsInterface);
} }
}
} }
@@ -77,7 +77,7 @@ internal class RegexExtended : Regex
/// <param name="pattern">Pattern to replace token for.</param> /// <param name="pattern">Pattern to replace token for.</param>
private static string ReplaceGuidPattern(string pattern) private static string ReplaceGuidPattern(string pattern)
{ {
Guard.NotNull(pattern, nameof(pattern)); Guard.NotNull(pattern);
foreach (var tokenPattern in GuidTokenPatterns) foreach (var tokenPattern in GuidTokenPatterns)
{ {
+2 -2
View File
@@ -47,10 +47,10 @@ public class RequestMessage : IRequestMessage
public string Method { get; } public string Method { get; }
/// <inheritdoc cref="IRequestMessage.Headers" /> /// <inheritdoc cref="IRequestMessage.Headers" />
public IDictionary<string, WireMockList<string>> Headers { get; } public IDictionary<string, WireMockList<string>>? Headers { get; }
/// <inheritdoc cref="IRequestMessage.Cookies" /> /// <inheritdoc cref="IRequestMessage.Cookies" />
public IDictionary<string, string> Cookies { get; } public IDictionary<string, string>? Cookies { get; }
/// <inheritdoc cref="IRequestMessage.Query" /> /// <inheritdoc cref="IRequestMessage.Query" />
public IDictionary<string, WireMockList<string>>? Query { get; } public IDictionary<string, WireMockList<string>>? Query { get; }
@@ -1,10 +1,10 @@
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// Defines the BodyDestinationFormat
/// </summary>
public static class BodyDestinationFormat
{ {
/// <summary>
/// Defines the BodyDestinationFormat
/// </summary>
public static class BodyDestinationFormat
{
/// <summary> /// <summary>
/// Same as source (no conversion) /// Same as source (no conversion)
/// </summary> /// </summary>
@@ -24,5 +24,4 @@
/// Convert to Json object /// Convert to Json object
/// </summary> /// </summary>
public const string Json = "Json"; public const string Json = "Json";
}
} }
@@ -2,13 +2,13 @@ using System;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// The BodyResponseBuilder interface.
/// </summary>
public interface IBodyResponseBuilder : IFaultResponseBuilder
{ {
/// <summary>
/// The BodyResponseBuilder interface.
/// </summary>
public interface IBodyResponseBuilder : IFaultResponseBuilder
{
/// <summary> /// <summary>
/// WithBody : Create a ... response based on a string. /// WithBody : Create a ... response based on a string.
/// </summary> /// </summary>
@@ -69,5 +69,4 @@ namespace WireMock.ResponseBuilders
/// <param name="cache">Defines if this file is cached in memory or retrieved from disk every time the response is created.</param> /// <param name="cache">Defines if this file is cached in memory or retrieved from disk every time the response is created.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithBodyFromFile(string filename, bool cache = true); IResponseBuilder WithBodyFromFile(string filename, bool cache = true);
}
} }
@@ -3,25 +3,24 @@ using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.ResponseProviders; using WireMock.ResponseProviders;
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// The CallbackResponseBuilder interface.
/// </summary>
public interface ICallbackResponseBuilder : IResponseProvider
{ {
/// <summary>
/// The CallbackResponseBuilder interface.
/// </summary>
public interface ICallbackResponseBuilder : IResponseProvider
{
/// <summary> /// <summary>
/// The callback builder /// The callback builder
/// </summary> /// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns> /// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI] [PublicAPI]
IResponseBuilder WithCallback([NotNull] Func<IRequestMessage, ResponseMessage> callbackHandler); IResponseBuilder WithCallback(Func<IRequestMessage, ResponseMessage> callbackHandler);
/// <summary> /// <summary>
/// The async callback builder /// The async callback builder
/// </summary> /// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns> /// <returns>The <see cref="IResponseBuilder"/>.</returns>
[PublicAPI] [PublicAPI]
IResponseBuilder WithCallback([NotNull] Func<IRequestMessage, Task<ResponseMessage>> callbackHandler); IResponseBuilder WithCallback(Func<IRequestMessage, Task<ResponseMessage>> callbackHandler);
}
} }
@@ -1,12 +1,12 @@
using System; using System;
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// The DelayResponseBuilder interface.
/// </summary>
public interface IDelayResponseBuilder : ICallbackResponseBuilder
{ {
/// <summary>
/// The DelayResponseBuilder interface.
/// </summary>
public interface IDelayResponseBuilder : ICallbackResponseBuilder
{
/// <summary> /// <summary>
/// The delay defined as a <see cref="TimeSpan"/>. /// The delay defined as a <see cref="TimeSpan"/>.
/// </summary> /// </summary>
@@ -28,5 +28,4 @@ namespace WireMock.ResponseBuilders
/// <param name="maximumMilliseconds">Maximum milliseconds to delay</param> /// <param name="maximumMilliseconds">Maximum milliseconds to delay</param>
/// <returns>The <see cref="IResponseBuilder"/>.</returns> /// <returns>The <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithRandomDelay(int minimumMilliseconds = 0, int maximumMilliseconds = 60_000); IResponseBuilder WithRandomDelay(int minimumMilliseconds = 0, int maximumMilliseconds = 60_000);
}
} }
@@ -1,18 +1,17 @@
using JetBrains.Annotations; using JetBrains.Annotations;
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// The FaultRequestBuilder interface.
/// </summary>
public interface IFaultResponseBuilder : ITransformResponseBuilder
{ {
/// <summary>
/// The FaultRequestBuilder interface.
/// </summary>
public interface IFaultResponseBuilder : ITransformResponseBuilder
{
/// <summary> /// <summary>
/// WithBody : Create a fault response. /// WithBody : Create a fault response.
/// </summary> /// </summary>
/// <param name="faultType">The FaultType.</param> /// <param name="faultType">The FaultType.</param>
/// <param name="percentage">The percentage when this fault should occur. When null, it's always a fault.</param> /// <param name="percentage">The percentage when this fault should occur. When null, it's always a fault.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithFault(FaultType faultType, [CanBeNull] double? percentage = null); IResponseBuilder WithFault(FaultType faultType, double? percentage = null);
}
} }
@@ -1,4 +1,3 @@
using JetBrains.Annotations;
using System.Collections.Generic; using System.Collections.Generic;
using WireMock.Types; using WireMock.Types;
@@ -1,20 +1,20 @@
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Settings; using WireMock.Settings;
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// The ProxyResponseBuilder interface.
/// </summary>
public interface IProxyResponseBuilder : IStatusCodeResponseBuilder
{ {
/// <summary>
/// The ProxyResponseBuilder interface.
/// </summary>
public interface IProxyResponseBuilder : IStatusCodeResponseBuilder
{
/// <summary> /// <summary>
/// WithProxy URL using Client X509Certificate2. /// WithProxy URL using Client X509Certificate2.
/// </summary> /// </summary>
/// <param name="proxyUrl">The proxy url.</param> /// <param name="proxyUrl">The proxy url.</param>
/// <param name="clientX509Certificate2ThumbprintOrSubjectName">The X509Certificate2 file to use for client authentication.</param> /// <param name="clientX509Certificate2ThumbprintOrSubjectName">The X509Certificate2 file to use for client authentication.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithProxy([NotNull] string proxyUrl, [CanBeNull] string clientX509Certificate2ThumbprintOrSubjectName = null); IResponseBuilder WithProxy(string proxyUrl, string? clientX509Certificate2ThumbprintOrSubjectName = null);
/// <summary> /// <summary>
/// WithProxy using IProxyAndRecordSettings. /// WithProxy using IProxyAndRecordSettings.
@@ -22,5 +22,4 @@ namespace WireMock.ResponseBuilders
/// <param name="settings">The IProxyAndRecordSettings.</param> /// <param name="settings">The IProxyAndRecordSettings.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithProxy([NotNull] ProxyAndRecordSettings settings); IResponseBuilder WithProxy([NotNull] ProxyAndRecordSettings settings);
}
} }
@@ -1,9 +1,8 @@
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// The ResponseBuilder interface.
/// </summary>
public interface IResponseBuilder : IProxyResponseBuilder
{ {
/// <summary>
/// The ResponseBuilder interface.
/// </summary>
public interface IResponseBuilder : IProxyResponseBuilder
{
}
} }
@@ -1,13 +1,13 @@
using System.Net; using System.Net;
using WireMock.Settings; using WireMock.Settings;
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// The StatusCodeResponseBuilder interface.
/// </summary>
public interface IStatusCodeResponseBuilder : IHeadersResponseBuilder
{ {
/// <summary>
/// The StatusCodeResponseBuilder interface.
/// </summary>
public interface IStatusCodeResponseBuilder : IHeadersResponseBuilder
{
/// <summary> /// <summary>
/// The with status code. /// The with status code.
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>. /// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
@@ -43,5 +43,4 @@ namespace WireMock.ResponseBuilders
/// </summary> /// </summary>
/// <returns>The <see cref="IResponseBuilder"/>.</returns> /// <returns>The <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithNotFound(); IResponseBuilder WithNotFound();
}
} }
@@ -1,12 +1,12 @@
using WireMock.Types; using WireMock.Types;
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// The TransformResponseBuilder interface.
/// </summary>
public interface ITransformResponseBuilder : IDelayResponseBuilder
{ {
/// <summary>
/// The TransformResponseBuilder interface.
/// </summary>
public interface ITransformResponseBuilder : IDelayResponseBuilder
{
/// <summary> /// <summary>
/// Use the Handlebars.Net ResponseMessage transformer. /// Use the Handlebars.Net ResponseMessage transformer.
/// </summary> /// </summary>
@@ -30,5 +30,4 @@ namespace WireMock.ResponseBuilders
/// The <see cref="IResponseBuilder"/>. /// The <see cref="IResponseBuilder"/>.
/// </returns> /// </returns>
IResponseBuilder WithTransformer(TransformerType transformerType = TransformerType.Handlebars, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None); IResponseBuilder WithTransformer(TransformerType transformerType = TransformerType.Handlebars, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None);
}
} }
@@ -1,20 +1,23 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using System.Threading.Tasks; using System.Threading.Tasks;
using Stef.Validation; using Stef.Validation;
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
public partial class Response
{ {
public partial class Response
{
/// <summary> /// <summary>
/// A delegate to execute to generate the response. /// A delegate to execute to generate the response.
/// </summary> /// </summary>
public Func<IRequestMessage, ResponseMessage> Callback { get; private set; } [MemberNotNullWhen(true, nameof(WithCallbackUsed))]
public Func<IRequestMessage, ResponseMessage>? Callback { get; private set; }
/// <summary> /// <summary>
/// A delegate to execute to generate the response async. /// A delegate to execute to generate the response async.
/// </summary> /// </summary>
public Func<IRequestMessage, Task<ResponseMessage>> CallbackAsync { get; private set; } [MemberNotNullWhen(true, nameof(WithCallbackUsed))]
public Func<IRequestMessage, Task<ResponseMessage>>? CallbackAsync { get; private set; }
/// <summary> /// <summary>
/// Defines if the method WithCallback(...) is used. /// Defines if the method WithCallback(...) is used.
@@ -24,7 +27,7 @@ namespace WireMock.ResponseBuilders
/// <inheritdoc /> /// <inheritdoc />
public IResponseBuilder WithCallback(Func<IRequestMessage, ResponseMessage> callbackHandler) public IResponseBuilder WithCallback(Func<IRequestMessage, ResponseMessage> callbackHandler)
{ {
Guard.NotNull(callbackHandler, nameof(callbackHandler)); Guard.NotNull(callbackHandler);
return WithCallbackInternal(true, callbackHandler); return WithCallbackInternal(true, callbackHandler);
} }
@@ -32,14 +35,14 @@ namespace WireMock.ResponseBuilders
/// <inheritdoc /> /// <inheritdoc />
public IResponseBuilder WithCallback(Func<IRequestMessage, Task<ResponseMessage>> callbackHandler) public IResponseBuilder WithCallback(Func<IRequestMessage, Task<ResponseMessage>> callbackHandler)
{ {
Guard.NotNull(callbackHandler, nameof(callbackHandler)); Guard.NotNull(callbackHandler);
return WithCallbackInternal(true, callbackHandler); return WithCallbackInternal(true, callbackHandler);
} }
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, ResponseMessage> callbackHandler) private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, ResponseMessage> callbackHandler)
{ {
Guard.NotNull(callbackHandler, nameof(callbackHandler)); Guard.NotNull(callbackHandler);
WithCallbackUsed = withCallbackUsed; WithCallbackUsed = withCallbackUsed;
Callback = callbackHandler; Callback = callbackHandler;
@@ -49,12 +52,11 @@ namespace WireMock.ResponseBuilders
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, Task<ResponseMessage>> callbackHandler) private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<IRequestMessage, Task<ResponseMessage>> callbackHandler)
{ {
Guard.NotNull(callbackHandler, nameof(callbackHandler)); Guard.NotNull(callbackHandler);
WithCallbackUsed = withCallbackUsed; WithCallbackUsed = withCallbackUsed;
CallbackAsync = callbackHandler; CallbackAsync = callbackHandler;
return this; return this;
} }
}
} }
@@ -1,7 +1,7 @@
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
public partial class Response
{ {
public partial class Response
{
/// <inheritdoc cref="IFaultResponseBuilder.WithFault(FaultType, double?)"/> /// <inheritdoc cref="IFaultResponseBuilder.WithFault(FaultType, double?)"/>
public IResponseBuilder WithFault(FaultType faultType, double? percentage = null) public IResponseBuilder WithFault(FaultType faultType, double? percentage = null)
{ {
@@ -10,5 +10,4 @@
return this; return this;
} }
}
} }
@@ -7,7 +7,7 @@ namespace WireMock.ResponseBuilders;
public partial class Response public partial class Response
{ {
private HttpClient _httpClientForProxy; private HttpClient? _httpClientForProxy;
/// <summary> /// <summary>
/// The WebProxy settings. /// The WebProxy settings.
+33 -34
View File
@@ -10,7 +10,6 @@ using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using Stef.Validation; using Stef.Validation;
using WireMock.Proxy; using WireMock.Proxy;
using WireMock.ResponseProviders;
using WireMock.Settings; using WireMock.Settings;
using WireMock.Transformers; using WireMock.Transformers;
using WireMock.Transformers.Handlebars; using WireMock.Transformers.Handlebars;
@@ -18,14 +17,14 @@ using WireMock.Transformers.Scriban;
using WireMock.Types; using WireMock.Types;
using WireMock.Util; using WireMock.Util;
namespace WireMock.ResponseBuilders namespace WireMock.ResponseBuilders;
/// <summary>
/// The Response.
/// </summary>
public partial class Response : IResponseBuilder
{ {
/// <summary> private static readonly ThreadLocal<Random> Random = new(() => new Random(DateTime.UtcNow.Millisecond));
/// The Response.
/// </summary>
public partial class Response : IResponseBuilder
{
private static readonly ThreadLocal<Random> Random = new ThreadLocal<Random>(() => new Random(DateTime.UtcNow.Millisecond));
private TimeSpan? _delay; private TimeSpan? _delay;
@@ -48,7 +47,7 @@ namespace WireMock.ResponseBuilders
{ {
if (MinimumDelayMilliseconds != null && MaximumDelayMilliseconds != null) if (MinimumDelayMilliseconds != null && MaximumDelayMilliseconds != null)
{ {
return TimeSpan.FromMilliseconds(Random.Value.Next(MinimumDelayMilliseconds.Value, MaximumDelayMilliseconds.Value)); return TimeSpan.FromMilliseconds(Random.Value!.Next(MinimumDelayMilliseconds.Value, MaximumDelayMilliseconds.Value));
} }
return _delay; return _delay;
@@ -88,7 +87,7 @@ namespace WireMock.ResponseBuilders
/// <param name="responseMessage">ResponseMessage</param> /// <param name="responseMessage">ResponseMessage</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI] [PublicAPI]
public static IResponseBuilder Create([CanBeNull] ResponseMessage responseMessage = null) public static IResponseBuilder Create(ResponseMessage? responseMessage = null)
{ {
var message = responseMessage ?? new ResponseMessage(); var message = responseMessage ?? new ResponseMessage();
return new Response(message); return new Response(message);
@@ -100,9 +99,9 @@ namespace WireMock.ResponseBuilders
/// <param name="func">The callback function.</param> /// <param name="func">The callback function.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
[PublicAPI] [PublicAPI]
public static IResponseBuilder Create([NotNull] Func<ResponseMessage> func) public static IResponseBuilder Create(Func<ResponseMessage> func)
{ {
Guard.NotNull(func, nameof(func)); Guard.NotNull(func);
return new Response(func()); return new Response(func());
} }
@@ -164,7 +163,7 @@ namespace WireMock.ResponseBuilders
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeader(string, string[])"/> /// <inheritdoc cref="IHeadersResponseBuilder.WithHeader(string, string[])"/>
public IResponseBuilder WithHeader(string name, params string[] values) public IResponseBuilder WithHeader(string name, params string[] values)
{ {
Guard.NotNull(name, nameof(name)); Guard.NotNull(name);
ResponseMessage.AddHeader(name, values); ResponseMessage.AddHeader(name, values);
return this; return this;
@@ -173,7 +172,7 @@ namespace WireMock.ResponseBuilders
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string})"/> /// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string})"/>
public IResponseBuilder WithHeaders(IDictionary<string, string> headers) public IResponseBuilder WithHeaders(IDictionary<string, string> headers)
{ {
Guard.NotNull(headers, nameof(headers)); Guard.NotNull(headers);
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value)); ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
return this; return this;
@@ -182,7 +181,7 @@ namespace WireMock.ResponseBuilders
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string[]})"/> /// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, string[]})"/>
public IResponseBuilder WithHeaders(IDictionary<string, string[]> headers) public IResponseBuilder WithHeaders(IDictionary<string, string[]> headers)
{ {
Guard.NotNull(headers, nameof(headers)); Guard.NotNull(headers);
ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value)); ResponseMessage.Headers = headers.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
return this; return this;
@@ -191,12 +190,14 @@ namespace WireMock.ResponseBuilders
/// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, WireMockList{string}})"/> /// <inheritdoc cref="IHeadersResponseBuilder.WithHeaders(IDictionary{string, WireMockList{string}})"/>
public IResponseBuilder WithHeaders(IDictionary<string, WireMockList<string>> headers) public IResponseBuilder WithHeaders(IDictionary<string, WireMockList<string>> headers)
{ {
Guard.NotNull(headers);
ResponseMessage.Headers = headers; ResponseMessage.Headers = headers;
return this; return this;
} }
/// <inheritdoc /> /// <inheritdoc />
public IResponseBuilder WithBody(Func<IRequestMessage, string> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null) public IResponseBuilder WithBody(Func<IRequestMessage, string> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null)
{ {
Guard.NotNull(bodyFactory, nameof(bodyFactory)); Guard.NotNull(bodyFactory, nameof(bodyFactory));
@@ -212,7 +213,7 @@ namespace WireMock.ResponseBuilders
} }
/// <inheritdoc /> /// <inheritdoc />
public IResponseBuilder WithBody(Func<IRequestMessage, Task<string>> bodyFactory, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null) public IResponseBuilder WithBody(Func<IRequestMessage, Task<string>> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null)
{ {
Guard.NotNull(bodyFactory, nameof(bodyFactory)); Guard.NotNull(bodyFactory, nameof(bodyFactory));
@@ -227,10 +228,10 @@ namespace WireMock.ResponseBuilders
}); });
} }
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(byte[], string, Encoding)"/> /// <inheritdoc />
public IResponseBuilder WithBody(byte[] body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null) public IResponseBuilder WithBody(byte[] body, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null)
{ {
Guard.NotNull(body, nameof(body)); Guard.NotNull(body);
ResponseMessage.BodyDestination = destination; ResponseMessage.BodyDestination = destination;
ResponseMessage.BodyData = new BodyData(); ResponseMessage.BodyData = new BodyData();
@@ -256,7 +257,7 @@ namespace WireMock.ResponseBuilders
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromFile"/> /// <inheritdoc cref="IBodyResponseBuilder.WithBodyFromFile"/>
public IResponseBuilder WithBodyFromFile(string filename, bool cache = true) public IResponseBuilder WithBodyFromFile(string filename, bool cache = true)
{ {
Guard.NotNull(filename, nameof(filename)); Guard.NotNull(filename);
ResponseMessage.BodyData = new BodyData ResponseMessage.BodyData = new BodyData
{ {
@@ -276,15 +277,14 @@ namespace WireMock.ResponseBuilders
return this; return this;
} }
/// <inheritdoc cref="IBodyResponseBuilder.WithBody(string, string, Encoding)"/> /// <inheritdoc />
public IResponseBuilder WithBody(string body, string destination = BodyDestinationFormat.SameAsSource, Encoding encoding = null) public IResponseBuilder WithBody(string body, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null)
{ {
Guard.NotNull(body, nameof(body)); Guard.NotNull(body);
encoding = encoding ?? Encoding.UTF8; encoding ??= Encoding.UTF8;
ResponseMessage.BodyDestination = destination; ResponseMessage.BodyDestination = destination;
ResponseMessage.BodyData = new BodyData ResponseMessage.BodyData = new BodyData
{ {
Encoding = encoding Encoding = encoding
@@ -312,9 +312,9 @@ namespace WireMock.ResponseBuilders
} }
/// <inheritdoc cref="IBodyResponseBuilder.WithBodyAsJson(object, Encoding, bool?)"/> /// <inheritdoc cref="IBodyResponseBuilder.WithBodyAsJson(object, Encoding, bool?)"/>
public IResponseBuilder WithBodyAsJson(object body, Encoding encoding = null, bool? indented = null) public IResponseBuilder WithBodyAsJson(object body, Encoding? encoding = null, bool? indented = null)
{ {
Guard.NotNull(body, nameof(body)); Guard.NotNull(body);
ResponseMessage.BodyDestination = null; ResponseMessage.BodyDestination = null;
ResponseMessage.BodyData = new BodyData ResponseMessage.BodyData = new BodyData
@@ -384,10 +384,10 @@ namespace WireMock.ResponseBuilders
} }
/// <inheritdoc /> /// <inheritdoc />
public async Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings) public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
{ {
Guard.NotNull(requestMessage, nameof(requestMessage)); Guard.NotNull(requestMessage);
Guard.NotNull(settings, nameof(settings)); Guard.NotNull(settings);
if (Delay != null) if (Delay != null)
{ {
@@ -431,7 +431,7 @@ namespace WireMock.ResponseBuilders
} }
else else
{ {
responseMessage = await CallbackAsync(requestMessage).ConfigureAwait(false); responseMessage = await CallbackAsync!(requestMessage).ConfigureAwait(false);
} }
// Copy StatusCode from ResponseMessage (if defined) // Copy StatusCode from ResponseMessage (if defined)
@@ -472,10 +472,9 @@ namespace WireMock.ResponseBuilders
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true) if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
{ {
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile); ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData!.BodyAsFile);
} }
return (responseMessage, null); return (responseMessage, null);
} }
}
} }
+13 -12
View File
@@ -7,24 +7,24 @@ using WireMock.Types;
using WireMock.Util; using WireMock.Util;
using Stef.Validation; using Stef.Validation;
namespace WireMock namespace WireMock;
/// <summary>
/// The ResponseMessage.
/// </summary>
public class ResponseMessage : IResponseMessage
{ {
/// <summary>
/// The ResponseMessage.
/// </summary>
public class ResponseMessage : IResponseMessage
{
/// <inheritdoc cref="IResponseMessage.Headers" /> /// <inheritdoc cref="IResponseMessage.Headers" />
public IDictionary<string, WireMockList<string>>? Headers { get; set; } = new Dictionary<string, WireMockList<string>>(); public IDictionary<string, WireMockList<string>>? Headers { get; set; } = new Dictionary<string, WireMockList<string>>();
/// <inheritdoc cref="IResponseMessage.StatusCode" /> /// <inheritdoc cref="IResponseMessage.StatusCode" />
public object StatusCode { get; set; } public object? StatusCode { get; set; }
/// <inheritdoc cref="IResponseMessage.BodyOriginal" /> /// <inheritdoc cref="IResponseMessage.BodyOriginal" />
public string BodyOriginal { get; set; } public string? BodyOriginal { get; set; }
/// <inheritdoc cref="IResponseMessage.BodyDestination" /> /// <inheritdoc cref="IResponseMessage.BodyDestination" />
public string BodyDestination { get; set; } public string? BodyDestination { get; set; }
/// <inheritdoc cref="IResponseMessage.BodyData" /> /// <inheritdoc cref="IResponseMessage.BodyData" />
public IBodyData? BodyData { get; set; } public IBodyData? BodyData { get; set; }
@@ -38,19 +38,20 @@ namespace WireMock
/// <inheritdoc cref="IResponseMessage.AddHeader(string, string)" /> /// <inheritdoc cref="IResponseMessage.AddHeader(string, string)" />
public void AddHeader(string name, string value) public void AddHeader(string name, string value)
{ {
Headers ??= new Dictionary<string, WireMockList<string>>();
Headers.Add(name, new WireMockList<string>(value)); Headers.Add(name, new WireMockList<string>(value));
} }
/// <inheritdoc cref="IResponseMessage.AddHeader(string, string[])" /> /// <inheritdoc cref="IResponseMessage.AddHeader(string, string[])" />
public void AddHeader(string name, params string[] values) public void AddHeader(string name, params string[] values)
{ {
Guard.NotNullOrEmpty(values, nameof(values)); Guard.NotNullOrEmpty(values);
var newHeaderValues = Headers.TryGetValue(name, out WireMockList<string> existingValues) Headers ??= new Dictionary<string, WireMockList<string>>();
var newHeaderValues = Headers.TryGetValue(name, out WireMockList<string>? existingValues)
? values.Union(existingValues).ToArray() ? values.Union(existingValues).ToArray()
: values; : values;
Headers[name] = new WireMockList<string>(newHeaderValues); Headers[name] = new WireMockList<string>(newHeaderValues);
} }
}
} }
@@ -2,10 +2,10 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using WireMock.Settings; using WireMock.Settings;
namespace WireMock.ResponseProviders namespace WireMock.ResponseProviders;
internal class DynamicAsyncResponseProvider : IResponseProvider
{ {
internal class DynamicAsyncResponseProvider : IResponseProvider
{
private readonly Func<IRequestMessage, Task<IResponseMessage>> _responseMessageFunc; private readonly Func<IRequestMessage, Task<IResponseMessage>> _responseMessageFunc;
public DynamicAsyncResponseProvider(Func<IRequestMessage, Task<IResponseMessage>> responseMessageFunc) public DynamicAsyncResponseProvider(Func<IRequestMessage, Task<IResponseMessage>> responseMessageFunc)
@@ -13,9 +13,8 @@ namespace WireMock.ResponseProviders
_responseMessageFunc = responseMessageFunc; _responseMessageFunc = responseMessageFunc;
} }
public async Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings) public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
{ {
return (await _responseMessageFunc(requestMessage).ConfigureAwait(false), null); return (await _responseMessageFunc(requestMessage).ConfigureAwait(false), null);
} }
}
} }
@@ -2,10 +2,10 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using WireMock.Settings; using WireMock.Settings;
namespace WireMock.ResponseProviders namespace WireMock.ResponseProviders;
internal class DynamicResponseProvider : IResponseProvider
{ {
internal class DynamicResponseProvider : IResponseProvider
{
private readonly Func<IRequestMessage, IResponseMessage> _responseMessageFunc; private readonly Func<IRequestMessage, IResponseMessage> _responseMessageFunc;
public DynamicResponseProvider(Func<IRequestMessage, IResponseMessage> responseMessageFunc) public DynamicResponseProvider(Func<IRequestMessage, IResponseMessage> responseMessageFunc)
@@ -13,10 +13,9 @@ namespace WireMock.ResponseProviders
_responseMessageFunc = responseMessageFunc; _responseMessageFunc = responseMessageFunc;
} }
public Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings) public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
{ {
(IResponseMessage responseMessage, IMapping mapping) result = (_responseMessageFunc(requestMessage), null); (IResponseMessage responseMessage, IMapping? mapping) result = (_responseMessageFunc(requestMessage), null);
return Task.FromResult(result); return Task.FromResult(result);
} }
}
} }
@@ -1,22 +1,20 @@
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License. // This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root. // For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations;
using WireMock.Settings; using WireMock.Settings;
namespace WireMock.ResponseProviders namespace WireMock.ResponseProviders;
/// <summary>
/// The Response Provider interface.
/// </summary>
public interface IResponseProvider
{ {
/// <summary>
/// The Response Provider interface.
/// </summary>
public interface IResponseProvider
{
/// <summary> /// <summary>
/// The provide response. /// The provide response.
/// </summary> /// </summary>
/// <param name="requestMessage">The request.</param> /// <param name="requestMessage">The request.</param>
/// <param name="settings">The WireMockServerSettings.</param> /// <param name="settings">The WireMockServerSettings.</param>
/// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns> /// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns>
Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync([NotNull] IRequestMessage requestMessage, [NotNull] WireMockServerSettings settings); Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings);
}
} }
@@ -2,10 +2,10 @@ using System;
using System.Threading.Tasks; using System.Threading.Tasks;
using WireMock.Settings; using WireMock.Settings;
namespace WireMock.ResponseProviders namespace WireMock.ResponseProviders;
internal class ProxyAsyncResponseProvider : IResponseProvider
{ {
internal class ProxyAsyncResponseProvider : IResponseProvider
{
private readonly Func<IRequestMessage, WireMockServerSettings, Task<IResponseMessage>> _responseMessageFunc; private readonly Func<IRequestMessage, WireMockServerSettings, Task<IResponseMessage>> _responseMessageFunc;
private readonly WireMockServerSettings _settings; private readonly WireMockServerSettings _settings;
@@ -15,9 +15,8 @@ namespace WireMock.ResponseProviders
_settings = settings; _settings = settings;
} }
public async Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings) public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
{ {
return (await _responseMessageFunc(requestMessage, _settings).ConfigureAwait(false), null); return (await _responseMessageFunc(requestMessage, _settings).ConfigureAwait(false), null);
} }
}
} }
@@ -140,7 +140,7 @@ internal static class LogEntryMapper
MatchDetails = matchResult.MatchDetails.Select(md => new MatchDetails = matchResult.MatchDetails.Select(md => new
{ {
Name = md.MatcherType.Name.Replace("RequestMessage", string.Empty), Name = md.MatcherType.Name.Replace("RequestMessage", string.Empty),
Score = md.Score md.Score
} as object).ToList() } as object).ToList()
}; };
} }
@@ -6,6 +6,7 @@ using Stef.Validation;
using WireMock.Admin.Mappings; using WireMock.Admin.Mappings;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
using WireMock.Models;
using WireMock.RequestBuilders; using WireMock.RequestBuilders;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
using WireMock.Settings; using WireMock.Settings;
@@ -116,9 +117,10 @@ internal class MappingConverter
mappingModel.Response.Delay = (int?)(response.Delay == Timeout.InfiniteTimeSpan ? TimeSpan.MaxValue.TotalMilliseconds : response.Delay?.TotalMilliseconds); mappingModel.Response.Delay = (int?)(response.Delay == Timeout.InfiniteTimeSpan ? TimeSpan.MaxValue.TotalMilliseconds : response.Delay?.TotalMilliseconds);
} }
if (mapping.Webhooks?.Length == 1) var nonNullableWebHooks = mapping.Webhooks?.Where(wh => wh != null).ToArray() ?? new IWebhook[0];
if (nonNullableWebHooks.Length == 1)
{ {
mappingModel.Webhook = WebhookMapper.Map(mapping.Webhooks[0]); mappingModel.Webhook = WebhookMapper.Map(nonNullableWebHooks[0]);
} }
else if (mapping.Webhooks?.Length > 1) else if (mapping.Webhooks?.Length > 1)
{ {
@@ -209,7 +211,7 @@ internal class MappingConverter
break; break;
} }
if (response.ResponseMessage.BodyData.Encoding != null && response.ResponseMessage.BodyData.Encoding.WebName != "utf-8") if (response.ResponseMessage.BodyData?.Encoding != null && response.ResponseMessage.BodyData.Encoding.WebName != "utf-8")
{ {
mappingModel.Response.BodyEncoding = new EncodingModel mappingModel.Response.BodyEncoding = new EncodingModel
{ {
@@ -22,10 +22,7 @@ internal class MappingToFileSaver
public void SaveMappingToFile(IMapping mapping, string? folder = null) public void SaveMappingToFile(IMapping mapping, string? folder = null)
{ {
if (folder == null) folder ??= _settings.FileSystemHandler.GetMappingFolder();
{
folder = _settings.FileSystemHandler.GetMappingFolder();
}
if (!_settings.FileSystemHandler.FolderExists(folder)) if (!_settings.FileSystemHandler.FolderExists(folder))
{ {
@@ -208,7 +208,7 @@ internal class MatcherMapper
return patternAsStringArray.ToAnyOfPatterns(); return patternAsStringArray.ToAnyOfPatterns();
} }
if (matcher.Patterns?.OfType<string>() is IEnumerable<string> patternsAsStringArray) if (matcher.Patterns?.OfType<string>() is { } patternsAsStringArray)
{ {
return patternsAsStringArray.ToAnyOfPatterns(); return patternsAsStringArray.ToAnyOfPatterns();
} }
+25 -9
View File
@@ -1,6 +1,7 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using DevLab.JmesPath.Interop;
using WireMock.Admin.Mappings; using WireMock.Admin.Mappings;
using WireMock.Extensions; using WireMock.Extensions;
using WireMock.Matchers; using WireMock.Matchers;
@@ -76,10 +77,25 @@ internal static class PactMapper
{ {
Status = MapStatusCode(response.StatusCode), Status = MapStatusCode(response.StatusCode),
Headers = MapResponseHeaders(response.Headers), Headers = MapResponseHeaders(response.Headers),
Body = response.BodyAsJson Body = MapBody(response)
}; };
} }
private static object? MapBody(ResponseModel? response)
{
if (response?.BodyAsJson != null)
{
return response.BodyAsJson;
}
if (response?.Body != null) // In case the body is a string, try to deserialize into object, else just return the string
{
return JsonUtils.TryDeserializeObject<object?>(response.Body) ?? response.Body;
}
return null;
}
private static int MapStatusCode(object? statusCode) private static int MapStatusCode(object? statusCode)
{ {
if (statusCode is string statusCodeAsString) if (statusCode is string statusCodeAsString)
@@ -138,13 +154,13 @@ internal static class PactMapper
return jsonMatcher?.Pattern; return jsonMatcher?.Pattern;
} }
private static string GetPatternAsStringFromMatchers(MatcherModel[]? matchers, string defaultValue) //private static string GetPatternAsStringFromMatchers(MatcherModel[]? matchers, string defaultValue)
{ //{
if (matchers != null && matchers.Any() && matchers[0].Pattern is string patternAsString) // if (matchers != null && matchers.Any() && matchers[0].Pattern is string patternAsString)
{ // {
return patternAsString; // return patternAsString;
} // }
return defaultValue; // return defaultValue;
} //}
} }
@@ -1,16 +1,17 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using Stef.Validation;
using WireMock.Admin.Mappings; using WireMock.Admin.Mappings;
using WireMock.Http; using WireMock.Http;
using WireMock.Models; using WireMock.Models;
using WireMock.Types; using WireMock.Types;
using WireMock.Util; using WireMock.Util;
namespace WireMock.Serialization namespace WireMock.Serialization;
internal static class WebhookMapper
{ {
internal static class WebhookMapper
{
public static IWebhook Map(WebhookModel model) public static IWebhook Map(WebhookModel model)
{ {
var webhook = new Webhook var webhook = new Webhook
@@ -40,8 +41,8 @@ namespace WireMock.Serialization
webhook.Request.TransformerReplaceNodeOptions = option; webhook.Request.TransformerReplaceNodeOptions = option;
} }
IEnumerable<string> contentTypeHeader = null; IEnumerable<string>? contentTypeHeader = null;
if (webhook.Request.Headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase))) if (webhook.Request.Headers != null && webhook.Request.Headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)))
{ {
contentTypeHeader = webhook.Request.Headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value; contentTypeHeader = webhook.Request.Headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value;
} }
@@ -70,10 +71,7 @@ namespace WireMock.Serialization
public static WebhookModel Map(IWebhook webhook) public static WebhookModel Map(IWebhook webhook)
{ {
if (webhook?.Request == null) Guard.NotNull(webhook);
{
return null;
}
var model = new WebhookModel var model = new WebhookModel
{ {
@@ -108,5 +106,4 @@ namespace WireMock.Serialization
return model; return model;
} }
}
} }
+28 -14
View File
@@ -292,7 +292,7 @@ public partial class WireMockServer
private IResponseMessage SettingsUpdate(IRequestMessage requestMessage) private IResponseMessage SettingsUpdate(IRequestMessage requestMessage)
{ {
var settings = DeserializeObject<SettingsModel>(requestMessage)!; var settings = DeserializeObject<SettingsModel>(requestMessage);
// _settings // _settings
_settings.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods; _settings.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods;
@@ -571,7 +571,7 @@ public partial class WireMockServer
{ {
var requestModel = DeserializeObject<RequestModel>(requestMessage); var requestModel = DeserializeObject<RequestModel>(requestMessage);
var request = (Request)InitRequestBuilder(requestModel, false); var request = (Request)InitRequestBuilder(requestModel, false)!;
var dict = new Dictionary<ILogEntry, RequestMatchResult>(); var dict = new Dictionary<ILogEntry, RequestMatchResult>();
foreach (var logEntry in LogEntries.Where(le => !le.RequestMessage.Path.StartsWith("/__admin/"))) foreach (var logEntry in LogEntries.Where(le => !le.RequestMessage.Path.StartsWith("/__admin/")))
@@ -625,6 +625,23 @@ public partial class WireMockServer
_settings.FileSystemHandler.WriteFile(folder, filenameUpdated, bytes); _settings.FileSystemHandler.WriteFile(folder, filenameUpdated, bytes);
} }
/// <summary>
/// Save the mappings as a Pact Json file V2.
/// </summary>
/// <param name="stream">The (file) stream.</param>
[PublicAPI]
public void SavePact(Stream stream)
{
var (_, bytes) = PactMapper.ToPact(this);
using var writer = new BinaryWriter(stream);
writer.Write(bytes);
if (stream.CanSeek)
{
stream.Seek(0, SeekOrigin.Begin);
}
}
/// <summary> /// <summary>
/// This stores details about the consumer of the interaction. /// This stores details about the consumer of the interaction.
/// </summary> /// </summary>
@@ -714,31 +731,28 @@ public partial class WireMockServer
}; };
} }
private static T? DeserializeObject<T>(IRequestMessage requestMessage) private static T DeserializeObject<T>(IRequestMessage requestMessage) where T : new()
{ {
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.String) return requestMessage.BodyData?.DetectedBodyType switch
{ {
return JsonUtils.DeserializeObject<T>(requestMessage.BodyData.BodyAsString); BodyType.String => JsonUtils.DeserializeObject<T>(requestMessage.BodyData.BodyAsString),
}
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json) BodyType.Json when requestMessage.BodyData?.BodyAsJson != null => ((JObject)requestMessage.BodyData.BodyAsJson).ToObject<T>()!,
{
return ((JObject)requestMessage.BodyData.BodyAsJson).ToObject<T>();
}
return default(T); _ => throw new NotSupportedException()
};
} }
private static T[] DeserializeRequestMessageToArray<T>(IRequestMessage requestMessage) private static T[] DeserializeRequestMessageToArray<T>(IRequestMessage requestMessage)
{ {
if (requestMessage.BodyData?.DetectedBodyType == BodyType.Json) if (requestMessage.BodyData?.DetectedBodyType == BodyType.Json && requestMessage.BodyData.BodyAsJson != null)
{ {
var bodyAsJson = requestMessage.BodyData.BodyAsJson; var bodyAsJson = requestMessage.BodyData.BodyAsJson;
return DeserializeObjectToArray<T>(bodyAsJson); return DeserializeObjectToArray<T>(bodyAsJson);
} }
return default(T[]); throw new NotSupportedException();
} }
private static T[] DeserializeJsonToArray<T>(string value) private static T[] DeserializeJsonToArray<T>(string value)
@@ -754,6 +768,6 @@ public partial class WireMockServer
} }
var singleResult = ((JObject)value).ToObject<T>(); var singleResult = ((JObject)value).ToObject<T>();
return new[] { singleResult }; return new[] { singleResult! };
} }
} }
@@ -275,7 +275,7 @@ public partial class WireMockServer
} }
else else
{ {
var headers = JsonUtils.ParseJTokenToObject<string[]>(entry.Value) ?? new string[0]; var headers = JsonUtils.ParseJTokenToObject<string[]>(entry.Value);
responseBuilder.WithHeader(entry.Key, headers); responseBuilder.WithHeader(entry.Key, headers);
} }
} }
@@ -2,18 +2,18 @@ using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
namespace WireMock.Settings namespace WireMock.Settings;
// Based on http://blog.gauffin.org/2014/12/simple-command-line-parser/
internal class SimpleCommandLineParser
{ {
// Based on http://blog.gauffin.org/2014/12/simple-command-line-parser/
internal class SimpleCommandLineParser
{
private const string Sigil = "--"; private const string Sigil = "--";
private IDictionary<string, string[]> Arguments { get; } = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase); private IDictionary<string, string[]> Arguments { get; } = new Dictionary<string, string[]>(StringComparer.OrdinalIgnoreCase);
public void Parse(string[] arguments) public void Parse(string[] arguments)
{ {
string currentName = null; string currentName = string.Empty;
var values = new List<string>(); var values = new List<string>();
@@ -51,21 +51,31 @@ namespace WireMock.Settings
return Arguments.ContainsKey(name); return Arguments.ContainsKey(name);
} }
public string[] GetValues(string name, string[] defaultValue = null) public string[] GetValues(string name, string[] defaultValue)
{ {
return Contains(name) ? Arguments[name] : defaultValue; return Contains(name) ? Arguments[name] : defaultValue;
} }
public T GetValue<T>(string name, Func<string[], T> func, T defaultValue = default(T)) public string[]? GetValues(string name)
{
return Contains(name) ? Arguments[name] : default;
}
public T GetValue<T>(string name, Func<string[], T> func, T defaultValue)
{ {
return Contains(name) ? func(Arguments[name]) : defaultValue; return Contains(name) ? func(Arguments[name]) : defaultValue;
} }
public T? GetValue<T>(string name, Func<string[], T> func)
{
return Contains(name) ? func(Arguments[name]) : default;
}
public bool GetBoolValue(string name, bool defaultValue = false) public bool GetBoolValue(string name, bool defaultValue = false)
{ {
return GetValue(name, values => return GetValue(name, values =>
{ {
string value = values.FirstOrDefault(); var value = values.FirstOrDefault();
return !string.IsNullOrEmpty(value) ? bool.Parse(value) : defaultValue; return !string.IsNullOrEmpty(value) ? bool.Parse(value) : defaultValue;
}, defaultValue); }, defaultValue);
} }
@@ -79,14 +89,18 @@ namespace WireMock.Settings
{ {
return GetValue(name, values => return GetValue(name, values =>
{ {
string value = values.FirstOrDefault(); var value = values.FirstOrDefault();
return !string.IsNullOrEmpty(value) ? int.Parse(value) : defaultValue; return !string.IsNullOrEmpty(value) ? int.Parse(value) : defaultValue;
}, defaultValue); }, defaultValue);
} }
public string GetStringValue(string name, string defaultValue = null) public string GetStringValue(string name, string defaultValue)
{ {
return GetValue(name, values => values.FirstOrDefault() ?? defaultValue, defaultValue); return GetValue(name, values => values.FirstOrDefault() ?? defaultValue, defaultValue);
} }
public string? GetStringValue(string name)
{
return GetValue(name, values => values.FirstOrDefault());
} }
} }
+6 -7
View File
@@ -1,9 +1,8 @@
namespace WireMock.Settings namespace WireMock.Settings;
/// <summary>
/// WebhookSettings
/// </summary>
public class WebhookSettings : HttpClientSettings
{ {
/// <summary>
/// WebhookSettings
/// </summary>
public class WebhookSettings : HttpClientSettings
{
}
} }
@@ -251,5 +251,11 @@ namespace WireMock.Settings
/// </summary> /// </summary>
[PublicAPI, JsonIgnore] [PublicAPI, JsonIgnore]
public IDictionary<string, Func<MatcherModel, IMatcher>>? CustomMatcherMappings { get; set; } public IDictionary<string, Func<MatcherModel, IMatcher>>? CustomMatcherMappings { get; set; }
/// <summary>
/// The <see cref="JsonSerializerSettings"/> used when the a JSON response is generated.
/// </summary>
[PublicAPI, JsonIgnore]
public JsonSerializerSettings? JsonSerializerSettings { get; set; }
} }
} }
@@ -1,16 +1,17 @@
using System; using System;
using System.Diagnostics.CodeAnalysis;
using JetBrains.Annotations; using JetBrains.Annotations;
using Stef.Validation; using Stef.Validation;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Types; using WireMock.Types;
namespace WireMock.Settings namespace WireMock.Settings;
/// <summary>
/// A static helper class to parse commandline arguments into WireMockServerSettings.
/// </summary>
public static class WireMockServerSettingsParser
{ {
/// <summary>
/// A static helper class to parse commandline arguments into WireMockServerSettings.
/// </summary>
public static class WireMockServerSettingsParser
{
/// <summary> /// <summary>
/// Parse commandline arguments into WireMockServerSettings. /// Parse commandline arguments into WireMockServerSettings.
/// </summary> /// </summary>
@@ -18,7 +19,7 @@ namespace WireMock.Settings
/// <param name="logger">The logger (optional, can be null)</param> /// <param name="logger">The logger (optional, can be null)</param>
/// <param name="settings">The parsed settings</param> /// <param name="settings">The parsed settings</param>
[PublicAPI] [PublicAPI]
public static bool TryParseArguments([NotNull] string[] args, out WireMockServerSettings settings, [CanBeNull] IWireMockLogger logger = null) public static bool TryParseArguments(string[] args, [NotNullWhen(true)] out WireMockServerSettings? settings, IWireMockLogger? logger = null)
{ {
Guard.HasNoNulls(args, nameof(args)); Guard.HasNoNulls(args, nameof(args));
@@ -82,7 +83,7 @@ namespace WireMock.Settings
settings.Urls = parser.GetValues("Urls", new[] { "http://*:9091/" }); settings.Urls = parser.GetValues("Urls", new[] { "http://*:9091/" });
} }
string proxyUrl = parser.GetStringValue("ProxyURL") ?? parser.GetStringValue("ProxyUrl"); var proxyUrl = parser.GetStringValue("ProxyURL") ?? parser.GetStringValue("ProxyUrl");
if (!string.IsNullOrEmpty(proxyUrl)) if (!string.IsNullOrEmpty(proxyUrl))
{ {
settings.ProxyAndRecordSettings = new ProxyAndRecordSettings settings.ProxyAndRecordSettings = new ProxyAndRecordSettings
@@ -93,12 +94,12 @@ namespace WireMock.Settings
ExcludedHeaders = parser.GetValues("ExcludedHeaders"), ExcludedHeaders = parser.GetValues("ExcludedHeaders"),
// PreferProxyMapping = parser.GetBoolValue(nameof(ProxyAndRecordSettings.PreferProxyMapping)), // PreferProxyMapping = parser.GetBoolValue(nameof(ProxyAndRecordSettings.PreferProxyMapping)),
SaveMapping = parser.GetBoolValue("SaveMapping"), SaveMapping = parser.GetBoolValue("SaveMapping"),
SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern"), SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern", "*"),
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"), SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
Url = proxyUrl Url = proxyUrl
}; };
string proxyAddress = parser.GetStringValue("WebProxyAddress"); string? proxyAddress = parser.GetStringValue("WebProxyAddress");
if (!string.IsNullOrEmpty(proxyAddress)) if (!string.IsNullOrEmpty(proxyAddress))
{ {
settings.ProxyAndRecordSettings.WebProxySettings = new WebProxySettings settings.ProxyAndRecordSettings.WebProxySettings = new WebProxySettings
@@ -125,5 +126,4 @@ namespace WireMock.Settings
return true; return true;
} }
}
} }
@@ -17,7 +17,7 @@ namespace WireMock.Util
private const int DefaultWatchInterval = 100; private const int DefaultWatchInterval = 100;
// This Dictionary keeps the track of when an event occurred last for a particular file // This Dictionary keeps the track of when an event occurred last for a particular file
private ConcurrentDictionary<string, DateTime> _lastFileEvent; private ConcurrentDictionary<string, DateTime> _lastFileEvent = new();
// Watch Interval in Milliseconds // Watch Interval in Milliseconds
private int _interval; private int _interval;
@@ -58,7 +58,7 @@ namespace WireMock.Util
/// <param name="interval">The interval.</param> /// <param name="interval">The interval.</param>
public EnhancedFileSystemWatcher(int interval = DefaultWatchInterval) public EnhancedFileSystemWatcher(int interval = DefaultWatchInterval)
{ {
Guard.Condition(interval, i => i >= 0, nameof(interval)); Guard.Condition(interval, i => i >= 0);
InitializeMembers(interval); InitializeMembers(interval);
} }
@@ -68,10 +68,10 @@ namespace WireMock.Util
/// </summary> /// </summary>
/// <param name="path">The directory to monitor, in standard or Universal Naming Convention (UNC) notation.</param> /// <param name="path">The directory to monitor, in standard or Universal Naming Convention (UNC) notation.</param>
/// <param name="interval">The interval.</param> /// <param name="interval">The interval.</param>
public EnhancedFileSystemWatcher([NotNull] string path, int interval = DefaultWatchInterval) : base(path) public EnhancedFileSystemWatcher(string path, int interval = DefaultWatchInterval) : base(path)
{ {
Guard.NotNullOrEmpty(path, nameof(path)); Guard.NotNullOrEmpty(path);
Guard.Condition(interval, i => i >= 0, nameof(interval)); Guard.Condition(interval, i => i >= 0);
InitializeMembers(interval); InitializeMembers(interval);
} }
@@ -82,11 +82,11 @@ namespace WireMock.Util
/// <param name="path">The directory to monitor, in standard or Universal Naming Convention (UNC) notation.</param> /// <param name="path">The directory to monitor, in standard or Universal Naming Convention (UNC) notation.</param>
/// <param name="filter">The type of files to watch. For example, "*.txt" watches for changes to all text files.</param> /// <param name="filter">The type of files to watch. For example, "*.txt" watches for changes to all text files.</param>
/// <param name="interval">The interval.</param> /// <param name="interval">The interval.</param>
public EnhancedFileSystemWatcher([NotNull] string path, [NotNull] string filter, int interval = DefaultWatchInterval) : base(path, filter) public EnhancedFileSystemWatcher(string path, string filter, int interval = DefaultWatchInterval) : base(path, filter)
{ {
Guard.NotNullOrEmpty(path, nameof(path)); Guard.NotNullOrEmpty(path);
Guard.NotNullOrEmpty(filter, nameof(filter)); Guard.NotNullOrEmpty(filter);
Guard.Condition(interval, i => i >= 0, nameof(interval)); Guard.Condition(interval, i => i >= 0);
InitializeMembers(interval); InitializeMembers(interval);
} }
@@ -100,22 +100,22 @@ namespace WireMock.Util
/// <summary> /// <summary>
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is changed. /// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is changed.
/// </summary> /// </summary>
public new event FileSystemEventHandler Changed; public new event FileSystemEventHandler? Changed;
/// <summary> /// <summary>
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is created. /// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is created.
/// </summary> /// </summary>
public new event FileSystemEventHandler Created; public new event FileSystemEventHandler? Created;
/// <summary> /// <summary>
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is deleted. /// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is deleted.
/// </summary> /// </summary>
public new event FileSystemEventHandler Deleted; public new event FileSystemEventHandler? Deleted;
/// <summary> /// <summary>
/// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is renamed. /// Occurs when a file or directory in the specified <see cref="P:System.IO.FileSystemWatcher.Path" /> is renamed.
/// </summary> /// </summary>
public new event RenamedEventHandler Renamed; public new event RenamedEventHandler? Renamed;
#endregion #endregion
#region Protected Methods to raise the Events for this class #region Protected Methods to raise the Events for this class
@@ -16,7 +16,7 @@ internal static class HttpStatusRangeParser
/// <param name="pattern">The pattern. (Can be null, in that case it's allowed.)</param> /// <param name="pattern">The pattern. (Can be null, in that case it's allowed.)</param>
/// <param name="httpStatusCode">The value.</param> /// <param name="httpStatusCode">The value.</param>
/// <exception cref="ArgumentException"><paramref name="pattern"/> is invalid.</exception> /// <exception cref="ArgumentException"><paramref name="pattern"/> is invalid.</exception>
public static bool IsMatch(string pattern, object httpStatusCode) public static bool IsMatch(string pattern, object? httpStatusCode)
{ {
switch (httpStatusCode) switch (httpStatusCode)
{ {
+27 -9
View File
@@ -87,9 +87,9 @@ internal static class JsonUtils
/// </summary> /// </summary>
/// <param name="json">A System.String that contains JSON.</param> /// <param name="json">A System.String that contains JSON.</param>
/// <returns>A Newtonsoft.Json.Linq.JToken populated from the string that contains JSON.</returns> /// <returns>A Newtonsoft.Json.Linq.JToken populated from the string that contains JSON.</returns>
public static JToken? Parse(string json) public static JToken Parse(string json)
{ {
return JsonConvert.DeserializeObject<JToken>(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone); return JsonConvert.DeserializeObject<JToken>(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone)!;
} }
/// <summary> /// <summary>
@@ -98,9 +98,9 @@ internal static class JsonUtils
/// </summary> /// </summary>
/// <param name="json">A System.String that contains JSON.</param> /// <param name="json">A System.String that contains JSON.</param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
public static object? DeserializeObject(string json) public static object DeserializeObject(string json)
{ {
return JsonConvert.DeserializeObject(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone); return JsonConvert.DeserializeObject(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone)!;
} }
/// <summary> /// <summary>
@@ -109,17 +109,35 @@ internal static class JsonUtils
/// </summary> /// </summary>
/// <param name="json">A System.String that contains JSON.</param> /// <param name="json">A System.String that contains JSON.</param>
/// <returns>The deserialized object from the JSON string.</returns> /// <returns>The deserialized object from the JSON string.</returns>
public static T? DeserializeObject<T>(string json) public static T DeserializeObject<T>(string json)
{ {
return JsonConvert.DeserializeObject<T>(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone); return JsonConvert.DeserializeObject<T>(json, JsonSerializationConstants.JsonDeserializerSettingsWithDateParsingNone)!;
} }
public static T? ParseJTokenToObject<T>(object value) public static T? TryDeserializeObject<T>(string json)
{ {
try
{
return JsonConvert.DeserializeObject<T>(json);
}
catch
{
return default;
}
}
public static T ParseJTokenToObject<T>(object? value)
{
if (value != null && value.GetType() == typeof(T))
{
return (T)value;
}
return value switch return value switch
{ {
JToken tokenValue => tokenValue.ToObject<T>(), JToken tokenValue => tokenValue.ToObject<T>()!,
_ => default
_ => throw new NotSupportedException($"Unable to convert value to {typeof(T)}.")
}; };
} }
+12 -9
View File
@@ -1,15 +1,16 @@
using System.IO; using System.IO;
using Stef.Validation;
namespace WireMock.Util namespace WireMock.Util;
internal static class PathUtils
{ {
internal static class PathUtils
{
/// <summary> /// <summary>
/// Robust handling of the user defined path. /// Robust handling of the user defined path.
/// Also supports Unix and Windows platforms /// Also supports Unix and Windows platforms
/// </summary> /// </summary>
/// <param name="path">The path to clean</param> /// <param name="path">The path to clean</param>
public static string CleanPath(string path) public static string? CleanPath(string? path)
{ {
return path?.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar); return path?.Replace('/', Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar);
} }
@@ -18,7 +19,7 @@ namespace WireMock.Util
/// Removes leading directory separator chars from the filepath, which could break Path.Combine /// Removes leading directory separator chars from the filepath, which could break Path.Combine
/// </summary> /// </summary>
/// <param name="path">The path to remove the loading DirectorySeparatorChars</param> /// <param name="path">The path to remove the loading DirectorySeparatorChars</param>
public static string RemoveLeadingDirectorySeparators(string path) public static string? RemoveLeadingDirectorySeparators(string? path)
{ {
return path?.TrimStart(new[] { Path.DirectorySeparatorChar }); return path?.TrimStart(new[] { Path.DirectorySeparatorChar });
} }
@@ -28,9 +29,11 @@ namespace WireMock.Util
/// </summary> /// </summary>
/// <param name="root">The root path</param> /// <param name="root">The root path</param>
/// <param name="path">The path</param> /// <param name="path">The path</param>
public static string Combine(string root, string path) public static string Combine(string root, string? path)
{ {
return Path.Combine(root, RemoveLeadingDirectorySeparators(path)); Guard.NotNull(root);
}
var result = RemoveLeadingDirectorySeparators(path);
return result == null ? root : Path.Combine(root, result);
} }
} }
+1 -1
View File
@@ -4,5 +4,5 @@ namespace WireMock.Util;
internal static class SystemUtils internal static class SystemUtils
{ {
public static readonly string Version = typeof(SystemUtils).GetTypeInfo().Assembly.GetName().Version.ToString(); public static readonly string Version = typeof(SystemUtils).GetTypeInfo().Assembly.GetName().Version!.ToString();
} }
+5
View File
@@ -140,6 +140,11 @@
<PackageReference Include="Scriban.Signed" Version="5.5.0" /> <PackageReference Include="Scriban.Signed" Version="5.5.0" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
<!--<PackageReference Include="System.Diagnostics.CodeAnalysis" Version="4.3.0" />-->
<PackageReference Include="Nullable" Version="1.3.0" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Update="Server\WireMockServer.*.cs"> <Compile Update="Server\WireMockServer.*.cs">
<DependentUpon>WireMockServer.cs</DependentUpon> <DependentUpon>WireMockServer.cs</DependentUpon>
+61 -1
View File
@@ -1,5 +1,9 @@
using System.IO; using System.IO;
using System.Net; using System.Net;
using System.Text;
using FluentAssertions;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.RequestBuilders; using WireMock.RequestBuilders;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
@@ -11,7 +15,7 @@ namespace WireMock.Net.Tests.Pact;
public class PactTests public class PactTests
{ {
[Fact] [Fact]
public void SavePact_Get_Request() public void SavePact_Get_Request_And_Response_WithBodyAsJson()
{ {
var server = WireMockServer.Start(); var server = WireMockServer.Start();
server server
@@ -41,6 +45,62 @@ public class PactTests
server.SavePact(Path.Combine("../../../", "Pact", "files"), "pact-get.json"); server.SavePact(Path.Combine("../../../", "Pact", "files"), "pact-get.json");
} }
[Fact]
public void SavePact_Get_Request_And_Response_WithBody_StringIsJson()
{
// Act
var server = WireMockServer.Start();
server
.Given(Request.Create()
.UsingGet()
.WithPath("/tester")
)
.RespondWith(
Response.Create()
.WithStatusCode(HttpStatusCode.OK)
.WithBody(@"{ foo: ""bar"" }")
);
var memoryStream = new MemoryStream();
server.SavePact(memoryStream);
var json = Encoding.UTF8.GetString(memoryStream.ToArray());
var pact = JsonConvert.DeserializeObject<WireMock.Pact.Models.V2.Pact>(json)!;
// Assert
pact.Interactions.Should().HaveCount(1);
var expectedBody = new JObject { { "foo", "bar" } };
pact.Interactions[0].Response.Body.Should().BeEquivalentTo(expectedBody);
}
[Fact]
public void SavePact_Get_Request_And_Response_WithBody_StringIsString()
{
// Act
var server = WireMockServer.Start();
server
.Given(Request.Create()
.UsingGet()
.WithPath("/tester")
)
.RespondWith(
Response.Create()
.WithStatusCode(HttpStatusCode.OK)
.WithBody("test")
);
var memoryStream = new MemoryStream();
server.SavePact(memoryStream);
var json = Encoding.UTF8.GetString(memoryStream.ToArray());
var pact = JsonConvert.DeserializeObject<WireMock.Pact.Models.V2.Pact>(json)!;
// Assert
pact.Interactions.Should().HaveCount(1);
pact.Interactions[0].Response.Body.Should().Be("test");
}
[Fact] [Fact]
public void SavePact_Multiple_Requests() public void SavePact_Multiple_Requests()
{ {
@@ -2,10 +2,10 @@ using NFluent;
using WireMock.Settings; using WireMock.Settings;
using Xunit; using Xunit;
namespace WireMock.Net.Tests.Settings namespace WireMock.Net.Tests.Settings;
public class SimpleCommandLineParserTests
{ {
public class SimpleCommandLineParserTests
{
private readonly SimpleCommandLineParser _parser; private readonly SimpleCommandLineParser _parser;
public SimpleCommandLineParserTests() public SimpleCommandLineParserTests()
@@ -20,9 +20,9 @@ namespace WireMock.Net.Tests.Settings
_parser.Parse(new[] { "--test1", "one", "--test2", "two", "--test3", "three" }); _parser.Parse(new[] { "--test1", "one", "--test2", "two", "--test3", "three" });
// Act // Act
string value1 = _parser.GetStringValue("test1"); string? value1 = _parser.GetStringValue("test1");
string value2 = _parser.GetStringValue("test2"); string? value2 = _parser.GetStringValue("test2");
string value3 = _parser.GetStringValue("test3"); string? value3 = _parser.GetStringValue("test3");
// Assert // Assert
Check.That(value1).IsEqualTo("one"); Check.That(value1).IsEqualTo("one");
@@ -37,9 +37,9 @@ namespace WireMock.Net.Tests.Settings
_parser.Parse(new[] { "--test1 one", "--test2 two", "--test3 three" }); _parser.Parse(new[] { "--test1 one", "--test2 two", "--test3 three" });
// Act // Act
string value1 = _parser.GetStringValue("test1"); string? value1 = _parser.GetStringValue("test1");
string value2 = _parser.GetStringValue("test2"); string? value2 = _parser.GetStringValue("test2");
string value3 = _parser.GetStringValue("test3"); string? value3 = _parser.GetStringValue("test3");
// Assert // Assert
Check.That(value1).IsEqualTo("one"); Check.That(value1).IsEqualTo("one");
@@ -54,9 +54,9 @@ namespace WireMock.Net.Tests.Settings
_parser.Parse(new[] { "--test1 one", "--test2", "two", "--test3 three" }); _parser.Parse(new[] { "--test1 one", "--test2", "two", "--test3 three" });
// Act // Act
string value1 = _parser.GetStringValue("test1"); string? value1 = _parser.GetStringValue("test1");
string value2 = _parser.GetStringValue("test2"); string? value2 = _parser.GetStringValue("test2");
string value3 = _parser.GetStringValue("test3"); string? value3 = _parser.GetStringValue("test3");
// Assert // Assert
Check.That(value1).IsEqualTo("one"); Check.That(value1).IsEqualTo("one");
@@ -99,5 +99,4 @@ namespace WireMock.Net.Tests.Settings
Check.That(value3).IsEqualTo(100); Check.That(value3).IsEqualTo(100);
Check.That(value4).IsNull(); Check.That(value4).IsNull();
} }
}
} }
+28 -2
View File
@@ -13,7 +13,7 @@ namespace WireMock.Net.Tests.Util;
public class JsonUtilsTests public class JsonUtilsTests
{ {
[Fact] [Fact]
public void JsonUtils_ParseJTokenToObject() public void JsonUtils_ParseJTokenToObject_For_String()
{ {
// Assign // Assign
object value = "test"; object value = "test";
@@ -22,7 +22,33 @@ public class JsonUtilsTests
string result = JsonUtils.ParseJTokenToObject<string>(value); string result = JsonUtils.ParseJTokenToObject<string>(value);
// Assert // Assert
Check.That(result).IsEqualTo(default(string)); result.Should().Be("test");
}
[Fact]
public void JsonUtils_ParseJTokenToObject_For_Int()
{
// Assign
object value = 123;
// Act
var result = JsonUtils.ParseJTokenToObject<int>(value);
// Assert
result.Should().Be(123);
}
[Fact]
public void JsonUtils_ParseJTokenToObject_For_Invalid_Throws()
{
// Assign
object value = "{ }";
// Act
Action action = () => JsonUtils.ParseJTokenToObject<int>(value);
// Assert
action.Should().Throw<NotSupportedException>();
} }
[Fact] [Fact]
@@ -1,12 +1,12 @@
using NFluent; using NFluent;
using System.IO; using System.IO;
using WireMock.Util; using WireMock.Util;
using Xunit; using Xunit;
namespace WireMock.Net.Tests.Util namespace WireMock.Net.Tests.Util;
public class PathUtilsTests
{ {
public class PathUtilsTests
{
[Theory] [Theory]
[InlineData(@"subdirectory/MyXmlResponse.xml")] [InlineData(@"subdirectory/MyXmlResponse.xml")]
[InlineData(@"subdirectory\MyXmlResponse.xml")] [InlineData(@"subdirectory\MyXmlResponse.xml")]
@@ -40,5 +40,4 @@ namespace WireMock.Net.Tests.Util
// Assert // Assert
Check.That(withoutDirectorySeparators).Equals(expected); Check.That(withoutDirectorySeparators).Equals(expected);
} }
}
} }
@@ -3,10 +3,10 @@ using NFluent;
using WireMock.Util; using WireMock.Util;
using Xunit; using Xunit;
namespace WireMock.Net.Tests.Util namespace WireMock.Net.Tests.Util;
public class PortUtilsTests
{ {
public class PortUtilsTests
{
[Fact] [Fact]
public void PortUtils_TryExtract_InvalidUrl_Returns_False() public void PortUtils_TryExtract_InvalidUrl_Returns_False()
{ {
@@ -85,10 +85,10 @@ namespace WireMock.Net.Tests.Util
bool result = PortUtils.TryExtract(url, out bool isHttps, out string proto, out string host, out int port); bool result = PortUtils.TryExtract(url, out bool isHttps, out string proto, out string host, out int port);
// Assert // Assert
Check.That(result).IsTrue(); result.Should().BeTrue();
Check.That(proto).IsEqualTo("https"); isHttps.Should().BeTrue();
Check.That(host).IsEqualTo("0.0.0.0"); proto.Should().Be("https");
Check.That(port).IsEqualTo(5000); host.Should().Be("0.0.0.0");
} port.Should().Be(5000);
} }
} }