Skip to content

Commit

Permalink
Add MappingBuilder to build mappings in code and export to Models or …
Browse files Browse the repository at this point in the history
…JSON (#869)

* MappingBuilder

* .

* ...

* sc

* t

* .
  • Loading branch information
StefH authored Jan 6, 2023
1 parent 742f1d1 commit 20eb37b
Show file tree
Hide file tree
Showing 10 changed files with 479 additions and 156 deletions.
14 changes: 14 additions & 0 deletions examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,20 @@ public static class MainApp
{
public static void Run()
{
var mappingBuilder = new MappingBuilder();
mappingBuilder
.Given(Request
.Create()
.WithPath(new WildcardMatcher("/param2", true))
.WithParam("key", "test")
.UsingGet())
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/json")
.WithBodyAsJson(new { result = "param2" }));

var json = mappingBuilder.ToJson();
System.Console.WriteLine("mappingBuilder : Json = {0}", json);

var s = WireMockServer.Start();
s.Stop();

Expand Down
43 changes: 43 additions & 0 deletions src/WireMock.Net/IMappingBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
using WireMock.Admin.Mappings;
using WireMock.Matchers.Request;
using WireMock.Server;

namespace WireMock;

/// <summary>
/// IMappingBuilder
/// </summary>
public interface IMappingBuilder
{
/// <summary>
/// The given.
/// </summary>
/// <param name="requestMatcher">The request matcher.</param>
/// <param name="saveToFile">Optional boolean to indicate if this mapping should be saved as static mapping file.</param>
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false);

/// <summary>
/// Gets all the mappings as a list.
/// </summary>
/// <returns>A list from <see cref="MappingModel"/>s.</returns>
MappingModel[] GetMappings();

/// <summary>
/// Convert all mappings to JSON.
/// </summary>
/// <returns>JSON</returns>
string ToJson();

/// <summary>
/// Save all mappings as a single JSON to a file.
/// </summary>
/// <param name="path">The file to write to.</param>
void SaveMappingsToFile(string path);

/// <summary>
/// Save all mappings as multiple JSON files (each file is 1 mapping).
/// </summary>
/// <param name="folder">The folder to write the files to.</param>
void SaveMappingsToFolder(string folder);
}
116 changes: 116 additions & 0 deletions src/WireMock.Net/MappingBuilder.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,116 @@
using System;
using System.Linq;
using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Admin.Mappings;
using WireMock.Matchers.Request;
using WireMock.Owin;
using WireMock.Serialization;
using WireMock.Server;
using WireMock.Settings;

namespace WireMock;

/// <summary>
/// MappingBuilder
/// </summary>
public class MappingBuilder : IMappingBuilder
{
private readonly WireMockServerSettings _settings;
private readonly IWireMockMiddlewareOptions _options;

private readonly MappingConverter _mappingConverter;
private readonly MappingToFileSaver _mappingToFileSaver;

/// <summary>
/// Create a MappingBuilder
/// </summary>
/// <param name="settings">The optional <see cref="WireMockServerSettings"/>.</param>
public MappingBuilder(WireMockServerSettings? settings = null)
{
_settings = settings ?? new WireMockServerSettings();
_options = WireMockMiddlewareOptionsHelper.InitFromSettings(_settings);

var matcherMapper = new MatcherMapper(_settings);
_mappingConverter = new MappingConverter(matcherMapper);
_mappingToFileSaver = new MappingToFileSaver(_settings, _mappingConverter);
}

internal MappingBuilder(
WireMockServerSettings settings,
IWireMockMiddlewareOptions options,
MappingConverter mappingConverter,
MappingToFileSaver mappingToFileSaver
)
{
_settings = Guard.NotNull(settings);
_options = Guard.NotNull(options);
_mappingConverter = Guard.NotNull(mappingConverter);
_mappingToFileSaver = Guard.NotNull(mappingToFileSaver);
}

/// <inheritdoc />
public IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false)
{
return new RespondWithAProvider(RegisterMapping, Guard.NotNull(requestMatcher), _settings, saveToFile);
}

/// <inheritdoc />
public MappingModel[] GetMappings()
{
return _options.Mappings.Values.ToArray()
.Where(m => !m.IsAdminInterface)
.Select(_mappingConverter.ToMappingModel)
.ToArray();
}

/// <inheritdoc />
public string ToJson()
{
return ToJson(GetMappings());
}

/// <inheritdoc />
public void SaveMappingsToFile(string path)
{
_mappingToFileSaver.SaveMappingsToFile(GetNonAdminMappings(), path);
}

/// <inheritdoc />
public void SaveMappingsToFolder(string? folder)
{
foreach (var mapping in GetNonAdminMappings().Where(m => !m.IsAdminInterface))
{
_mappingToFileSaver.SaveMappingToFile(mapping, folder);
}
}

private IMapping[] GetNonAdminMappings()
{
return _options.Mappings.Values.ToArray();
}

private void RegisterMapping(IMapping mapping, bool saveToFile)
{
// Check a mapping exists with the same Guid. If so, update the datetime and replace it.
if (_options.Mappings.ContainsKey(mapping.Guid))
{
mapping.UpdatedAt = DateTime.UtcNow;
_options.Mappings[mapping.Guid] = mapping;
}
else
{
_options.Mappings.TryAdd(mapping.Guid, mapping);
}

if (saveToFile)
{
_mappingToFileSaver.SaveMappingToFile(mapping);
}
}

private static string ToJson(object value)
{
return JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsDefault);
}
}
35 changes: 35 additions & 0 deletions src/WireMock.Net/Owin/WireMockMiddlewareOptionsHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
using Stef.Validation;
using WireMock.Settings;

namespace WireMock.Owin;

internal static class WireMockMiddlewareOptionsHelper
{
public static IWireMockMiddlewareOptions InitFromSettings(WireMockServerSettings settings, IWireMockMiddlewareOptions? options = null)
{
Guard.NotNull(settings);

options ??= new WireMockMiddlewareOptions();

options.FileSystemHandler = settings.FileSystemHandler;
options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit;
options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit;
options.Logger = settings.Logger;
options.DisableJsonBodyParsing = settings.DisableJsonBodyParsing;
options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
options.DoNotSaveDynamicResponseInLogEntry = settings.DoNotSaveDynamicResponseInLogEntry;
options.QueryParameterMultipleValueSupport = settings.QueryParameterMultipleValueSupport;

if (settings.CustomCertificateDefined)
{
options.X509StoreName = settings.CertificateSettings!.X509StoreName;
options.X509StoreLocation = settings.CertificateSettings.X509StoreLocation;
options.X509ThumbprintOrSubjectName = settings.CertificateSettings.X509StoreThumbprintOrSubjectName;
options.X509CertificateFilePath = settings.CertificateSettings.X509CertificateFilePath;
options.X509CertificatePassword = settings.CertificateSettings.X509CertificatePassword;
}

return options;
}
}
21 changes: 20 additions & 1 deletion src/WireMock.Net/Serialization/MappingToFileSaver.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,20 @@ public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mapp
_mappingConverter = Guard.NotNull(mappingConverter);
}

public void SaveMappingsToFile(IMapping[] mappings, string? folder = null)
{
folder ??= _settings.FileSystemHandler.GetMappingFolder();

if (!_settings.FileSystemHandler.FolderExists(folder))
{
_settings.FileSystemHandler.CreateFolder(folder);
}

var models = mappings.Select(_mappingConverter.ToMappingModel).ToArray();

Save(models, folder);
}

public void SaveMappingToFile(IMapping mapping, string? folder = null)
{
folder ??= _settings.FileSystemHandler.GetMappingFolder();
Expand All @@ -31,9 +45,14 @@ public void SaveMappingToFile(IMapping mapping, string? folder = null)
var filename = BuildSanitizedFileName(mapping);
var path = Path.Combine(folder, filename);

Save(model, path);
}

private void Save(object value, string path)
{
_settings.Logger.Info("Saving Mapping file {0}", path);

_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, JsonSerializationConstants.JsonSerializerSettingsDefault));
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsDefault));
}

private string BuildSanitizedFileName(IMapping mapping, char replaceChar = '_')
Expand Down
3 changes: 2 additions & 1 deletion src/WireMock.Net/Serialization/MatcherMapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Linq;
using AnyOfTypes;
using SimMetrics.Net;
using Stef.Validation;
using WireMock.Admin.Mappings;
using WireMock.Extensions;
using WireMock.Matchers;
Expand All @@ -19,7 +20,7 @@ internal class MatcherMapper

public MatcherMapper(WireMockServerSettings settings)
{
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
_settings = Guard.NotNull(settings);
}

public IMatcher[]? Map(IEnumerable<MatcherModel>? matchers)
Expand Down
30 changes: 12 additions & 18 deletions src/WireMock.Net/Server/WireMockServer.Admin.cs
Original file line number Diff line number Diff line change
Expand Up @@ -111,10 +111,7 @@ private void InitAdmin()
[PublicAPI]
public void SaveStaticMappings(string? folder = null)
{
foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface))
{
_mappingToFileSaver.SaveMappingToFile(mapping, folder);
}
_mappingBuilder.SaveMappingsToFolder(folder);
}

/// <inheritdoc cref="IWireMockServer.ReadStaticMappings" />
Expand Down Expand Up @@ -353,9 +350,9 @@ private IResponseMessage MappingsSave(IRequestMessage requestMessage)
return ResponseMessageBuilder.Create("Mappings saved to disk");
}

private IEnumerable<MappingModel> ToMappingModels()
private MappingModel[] ToMappingModels()
{
return Mappings.Where(m => !m.IsAdminInterface).Select(_mappingConverter.ToMappingModel);
return _mappingBuilder.GetMappings();
}

private IResponseMessage MappingsGet(IRequestMessage requestMessage)
Expand Down Expand Up @@ -418,18 +415,15 @@ private IResponseMessage MappingsDelete(IRequestMessage requestMessage)
try
{
var mappingModels = DeserializeRequestMessageToArray<MappingModel>(requestMessage);
foreach (var mappingModel in mappingModels)
foreach (var guid in mappingModels.Where(mm => mm.Guid.HasValue).Select(mm => mm.Guid!.Value))
{
if (mappingModel.Guid.HasValue)
if (DeleteMapping(guid))
{
deletedGuids.Add(guid);
}
else
{
if (DeleteMapping(mappingModel.Guid.Value))
{
deletedGuids.Add(mappingModel.Guid.Value);
}
else
{
_settings.Logger.Debug($"Did not find/delete mapping with GUID: {mappingModel.Guid.Value}.");
}
_settings.Logger.Debug($"Did not find/delete mapping with GUID: {guid}.");
}
}
}
Expand Down Expand Up @@ -697,7 +691,7 @@ private static ResponseMessage ToJson<T>(T result, bool keepNullValues = false)
{
return requestMessage.BodyData?.DetectedBodyType switch
{
BodyType.String => JsonUtils.DeserializeObject<T>(requestMessage.BodyData.BodyAsString),
BodyType.String => JsonUtils.DeserializeObject<T>(requestMessage.BodyData.BodyAsString!),

BodyType.Json when requestMessage.BodyData?.BodyAsJson != null => ((JObject)requestMessage.BodyData.BodyAsJson).ToObject<T>()!,

Expand Down Expand Up @@ -726,7 +720,7 @@ private static T[] DeserializeObjectToArray<T>(object value)
{
if (value is JArray jArray)
{
return jArray.ToObject<T[]>();
return jArray.ToObject<T[]>()!;
}

var singleResult = ((JObject)value).ToObject<T>();
Expand Down
Loading

0 comments on commit 20eb37b

Please sign in to comment.