Skip to content

Commit

Permalink
Add a custom json serializer when deserializing testfiles (#26)
Browse files Browse the repository at this point in the history
  • Loading branch information
coenm authored Nov 29, 2021
1 parent 4364fa4 commit bd358c7
Show file tree
Hide file tree
Showing 24 changed files with 470 additions and 18 deletions.
7 changes: 7 additions & 0 deletions EasyTestFile.sln
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyTestFile.Xunit.CopyPres
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyTestFile.Xunit.ModeNone.Tests", "tests\EasyTestFile.Xunit.ModeNone.Tests\EasyTestFile.Xunit.ModeNone.Tests.csproj", "{42805355-871E-4B35-9BB7-D168417D8860}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "EasyTestFile.Json.Tests", "tests\EasyTestFile.Json.Tests\EasyTestFile.Json.Tests.csproj", "{CF26070C-860B-421D-8697-1D04367BC3DD}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -100,6 +102,10 @@ Global
{42805355-871E-4B35-9BB7-D168417D8860}.Debug|Any CPU.Build.0 = Debug|Any CPU
{42805355-871E-4B35-9BB7-D168417D8860}.Release|Any CPU.ActiveCfg = Release|Any CPU
{42805355-871E-4B35-9BB7-D168417D8860}.Release|Any CPU.Build.0 = Release|Any CPU
{CF26070C-860B-421D-8697-1D04367BC3DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{CF26070C-860B-421D-8697-1D04367BC3DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
{CF26070C-860B-421D-8697-1D04367BC3DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
{CF26070C-860B-421D-8697-1D04367BC3DD}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -117,6 +123,7 @@ Global
{14927A45-6D1C-4B15-A18C-06AB7C7E97FB} = {3A849D71-FEE8-4494-A8A6-C303AAB18A42}
{B72DBB51-A84C-4E1A-A70E-3677971A04E5} = {3A849D71-FEE8-4494-A8A6-C303AAB18A42}
{42805355-871E-4B35-9BB7-D168417D8860} = {3A849D71-FEE8-4494-A8A6-C303AAB18A42}
{CF26070C-860B-421D-8697-1D04367BC3DD} = {3A849D71-FEE8-4494-A8A6-C303AAB18A42}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {E0B06F3E-E0CF-486F-9251-DB617317FE44}
Expand Down
61 changes: 61 additions & 0 deletions src/EasyTestFile.Json/EasyTestFileSettingsExtension.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
namespace EasyTestFile.Json;

using System;
using Newtonsoft.Json;

/// <summary>
///
/// </summary>
public static class EasyTestFileSettingsExtension
{
/// <summary>
/// Set <paramref name="jsonSerializer"/> as the default json serializer when deserializing testfiles.
/// </summary>
/// <param name="settings">The settings.</param>
/// <param name="jsonSerializer">The serializer.</param>
/// <exception cref="ArgumentNullException">Thrown when <paramref name="settings"/> or when <paramref name="jsonSerializer"/> is <c>null</c>.</exception>
/// <exception cref="Exception">Thrown when key cannot be inserted.</exception>
public static void SetNewtonSoftJsonSerializerSettings(this EasyTestFileSettings settings, JsonSerializer jsonSerializer)
{
if (settings == null)
{
throw new ArgumentNullException(nameof(settings));
}

if (jsonSerializer == null)
{
throw new ArgumentNullException(nameof(jsonSerializer));
}

if (settings.Context.ContainsKey(ExtensionKey.JSON_SERIALIZER))
{
settings.Context[ExtensionKey.JSON_SERIALIZER] = jsonSerializer;
return;
}

try
{
settings.Context.Add(ExtensionKey.JSON_SERIALIZER, jsonSerializer);
}
catch (Exception e)
{
throw new($"Could not add settings", e);
}
}

internal static JsonSerializer? GetNewtonSoftJsonSerializerSettings(this EasyTestFileSettings settings)
{
if (settings == null)
{
throw new ArgumentNullException(nameof(settings));
}

if (!settings.Context.TryGetValue(ExtensionKey.JSON_SERIALIZER, out var value))
{
return null;
}

return value as JsonSerializer;
}

}
11 changes: 11 additions & 0 deletions src/EasyTestFile.Json/ExtensionKey.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
namespace EasyTestFile.Json
{
using System;
using System.Collections.Generic;
using System.Text;

internal static class ExtensionKey
{
internal const string JSON_SERIALIZER = "Newtonsoft.Json.JsonSerializer";
}
}
35 changes: 30 additions & 5 deletions src/EasyTestFile.Json/NewtosoftDeserialize.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public static class NewtonsoftDeserialize
/// <summary>
/// Deserializes the <paramref name="testFile"/> using <see cref="Newtonsoft"/>.
/// </summary>
/// <param name="testFile">The TestFile. Cannot be null</param>
/// <param name="testFile">The TestFile. Cannot be <c>null</c>.</param>
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
/// <returns>The instance of <typeparamref name="T"/> being deserialized.</returns>
public static Task<T> AsObjectUsingNewtonsoft<T>(this TestFile testFile)
Expand All @@ -23,14 +23,39 @@ public static Task<T> AsObjectUsingNewtonsoft<T>(this TestFile testFile)
throw new ArgumentNullException(nameof(testFile));
}

return Task.FromResult(DeserializeFromStream<T>(testFile.AsStream()));
JsonSerializer? jsonSerializer = testFile.GetSettings().GetNewtonSoftJsonSerializerSettings();

return Task.FromResult(DeserializeFromStream<T>(
testFile.AsStream(),
jsonSerializer ?? new JsonSerializer()));
}

/// <summary>
/// Deserializes the <paramref name="testFile"/> using <see cref="Newtonsoft"/>.
/// </summary>
/// <param name="testFile">The TestFile. Cannot be <c>null</c>.</param>
/// <param name="serializer">Json serializer. Cannot be <c>null</c>.</param>
/// <typeparam name="T">The type of the object to deserialize.</typeparam>
/// <returns>The instance of <typeparamref name="T"/> being deserialized.</returns>
public static Task<T> AsObjectUsingNewtonsoft<T>(this TestFile testFile, JsonSerializer serializer)
{
if (testFile == null)
{
throw new ArgumentNullException(nameof(testFile));
}

if (serializer == null)
{
throw new ArgumentNullException(nameof(serializer));
}

return Task.FromResult(DeserializeFromStream<T>(testFile.AsStream(), serializer));
}

internal static T DeserializeFromStream<T>(Stream stream)
internal static T DeserializeFromStream<T>(Stream stream, JsonSerializer jsonSerializer)
{
var serializer = new JsonSerializer();
using var sr = new StreamReader(stream);
using var jsonTextReader = new JsonTextReader(sr);
return serializer.Deserialize<T>(jsonTextReader)!;
return jsonSerializer.Deserialize<T>(jsonTextReader)!;
}
}
2 changes: 1 addition & 1 deletion src/EasyTestFile.Json/PackageDescription.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ Testfiles (like text, json, xml, binary, jpg, etc. etc.) are named based on the

# EasyTestFile.Json

This package contains extension method(s) to deserialize TestFiles using json.
This package contains extension methods to deserialize TestFiles using json.

<!-- snippet: LoadJson -->
<a id='snippet-loadjson'></a>
Expand Down
17 changes: 17 additions & 0 deletions src/EasyTestFile/EasyTestFileSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,10 +31,27 @@ public EasyTestFileSettings(EasyTestFileSettings? settings)
AutoCreateMissingTestFileDisabled = settings.AutoCreateMissingTestFileDisabled;
TestFileNamingSuffix = settings.TestFileNamingSuffix;
Assembly = settings.Assembly;

foreach (KeyValuePair<string, object> pair in settings.Context)
{
if (pair.Value is ICloneable cloneable)
{
Context.Add(pair.Key, cloneable.Clone());
}
else
{
Context.Add(pair.Key, pair.Value);
}
}
}

internal bool AutoCreateMissingTestFileDisabled = false;

/// <summary>
/// Allows extensions to EasyTestFile to pass config via <see cref="EasyTestFileSettings"/>.
/// </summary>
public Dictionary<string, object> Context { get; } = new();

/// <summary>
/// Disable the creation of an empty test file when the file could not have been found.
/// </summary>
Expand Down
3 changes: 2 additions & 1 deletion src/EasyTestFile/InternalsVisibleTo.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,4 +6,5 @@
[assembly:InternalsVisibleTo("EasyTestFile.Xunit.Embed.Tests")]
[assembly:InternalsVisibleTo("EasyTestFile.Xunit.ModeNone.Tests")]
[assembly:InternalsVisibleTo("EasyTestFile.Nunit")]
[assembly: InternalsVisibleTo("EasyTestFile.Tests")]
[assembly:InternalsVisibleTo("EasyTestFile.Tests")]
[assembly:InternalsVisibleTo("EasyTestFile.Json")]
7 changes: 7 additions & 0 deletions src/EasyTestFile/TestFile.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
namespace EasyTestFile;

using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using System.Threading.Tasks;
Expand Down Expand Up @@ -69,4 +70,10 @@ public Stream AsStream()

throw new TestFileNotFoundException(operatingSystemFullFilename, created);
}

internal EasyTestFileSettings GetSettings()
{
return _settings;
}

}
25 changes: 25 additions & 0 deletions tests/EasyTestFile.Json.Tests/EasyTestFile.Json.Tests.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netcoreapp2.1;netcoreapp3.1;net5;net6</TargetFrameworks>
<RootNamespace>EasyTestFile.Json.Tests</RootNamespace>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\..\src\EasyTestFile.Json\EasyTestFile.Json.csproj" />
<ProjectReference Include="..\..\src\EasyTestFile.Xunit\EasyTestFile.Xunit.csproj" />
<ProjectReference Include="..\..\src\EasyTestFile\EasyTestFile.csproj" />
<PackageReference Include="Verify.Xunit" />
<PackageReference Include="xunit" />
<PackageReference Include="xunit.analyzers" />
<PackageReference Include="xunit.categories" />
<PackageReference Include="xunit.runner.console" />
<PackageReference Include="xunit.runner.visualstudio">
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<PackageReference Include="xunit.runner.reporters">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>
70 changes: 70 additions & 0 deletions tests/EasyTestFile.Json.Tests/EasyTestFileSettingsExtensionTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
namespace EasyTestFile.Json.Tests;

using System;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Threading.Tasks;
using FluentAssertions;
using Newtonsoft.Json;
using VerifyXunit;
using Xunit;
using Sut = EasyTestFileSettingsExtension;

[UsesVerify]
[SuppressMessage("ReSharper", "InvokeAsExtensionMethod", Justification = "Improves readability SUT.")]
public class EasyTestFileSettingsExtensionTest
{
[Fact]
public void SetNewtonSoftJsonSerializerSettings_ShouldSaveSettingsInContext()
{
// arrange
var settings = new EasyTestFileSettings();
var jsonSerializer = new JsonSerializer();

// act
Sut.SetNewtonSoftJsonSerializerSettings(settings, jsonSerializer);

// assert
settings.Context.Should().ContainKey("Newtonsoft.Json.JsonSerializer").WhoseValue.Should().BeSameAs(jsonSerializer);
}

[Fact]
public void SetNewtonSoftJsonSerializerSettings_ShouldOverrideSettingsInContext_WhenAlreadyStored()
{
// arrange
var settings = new EasyTestFileSettings();
var jsonSerializer1 = new JsonSerializer();
var jsonSerializer2 = new JsonSerializer();
Sut.SetNewtonSoftJsonSerializerSettings(settings, jsonSerializer1);

// act
Sut.SetNewtonSoftJsonSerializerSettings(settings, jsonSerializer2);

// assert
settings.Context.Should().ContainKey("Newtonsoft.Json.JsonSerializer").WhoseValue.Should().BeSameAs(jsonSerializer2);
}

[Fact]
public void SetNewtonSoftJsonSerializerSettings_ShouldThrow_WhenSettingsArgumentIsNull()
{
// arrange

// act
Action act = () => Sut.SetNewtonSoftJsonSerializerSettings(null!, new JsonSerializer());

// assert
act.Should().ThrowExactly<ArgumentNullException>();
}

[Fact]
public void SetNewtonSoftJsonSerializerSettings_ShouldThrow_WhenJsonSerializerArgumentIsNull()
{
// arrange

// act
Action act = () => Sut.SetNewtonSoftJsonSerializerSettings(new EasyTestFileSettings(), null!);

// assert
act.Should().ThrowExactly<ArgumentNullException>();
}
}
23 changes: 23 additions & 0 deletions tests/EasyTestFile.Json.Tests/EasyTestFileSettingsTest.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
namespace EasyTestFile.Json.Tests;

using FluentAssertions;
using Newtonsoft.Json;
using Xunit;

public class EasyTestFileSettingsTest
{
[Fact]
public void Ctor_ShouldCopyJsonSerializer_WhenSetInBase()
{
// arrange
var settings1 = new EasyTestFileSettings();
var jsonSerializer = new JsonSerializer();
settings1.SetNewtonSoftJsonSerializerSettings(jsonSerializer);

// act
var settings2 = new EasyTestFileSettings(settings1);

// assert
settings1.Context.Should().BeEquivalentTo(settings2.Context);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"$type": "EasyTestFile.Json.Tests.TestEntities.TestEntity, EasyTestFile.Json.Tests",
"Name": "CoenM",
"DateOfBirth": "2020-03-05T04:14:12",
"Subs": {
"$type": "System.Collections.Generic.List`1[[EasyTestFile.Json.Tests.TestEntities.SubTestEntity, EasyTestFile.Json.Tests]], System.Private.CoreLib",
"$values": [
{
"$type": "EasyTestFile.Json.Tests.TestEntities.SubTestEntity, EasyTestFile.Json.Tests",
"Id": "073633d2-edd1-4a1d-93b7-fa4a8b1b1a03"
},
{
"$type": "EasyTestFile.Json.Tests.TestEntities.SubTestEntity, EasyTestFile.Json.Tests",
"Id": "841e3836-b1b2-4e45-979e-e0b2ad8fad38"
},
{
"$type": "EasyTestFile.Json.Tests.TestEntities.SubTestEntity, EasyTestFile.Json.Tests",
"Id": "86e2fb0b-30a8-4688-ad24-f7da9385c43c"
}
]
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
{
"$type": "EasyTestFile.Json.Tests.TestEntities.TestEntity, EasyTestFile.Json.Tests",
"Name": "CoenM",
"DateOfBirth": "2020-03-05T04:14:12",
"Subs": {
"$type": "System.Collections.Generic.List`1[[EasyTestFile.Json.Tests.TestEntities.SubTestEntity, EasyTestFile.Json.Tests]], System.Private.CoreLib",
"$values": [
{
"$type": "EasyTestFile.Json.Tests.TestEntities.SubTestEntity, EasyTestFile.Json.Tests",
"Id": "073633d2-edd1-4a1d-93b7-fa4a8b1b1a03"
},
{
"$type": "EasyTestFile.Json.Tests.TestEntities.SubTestEntity, EasyTestFile.Json.Tests",
"Id": "841e3836-b1b2-4e45-979e-e0b2ad8fad38"
},
{
"$type": "EasyTestFile.Json.Tests.TestEntities.SubTestEntity, EasyTestFile.Json.Tests",
"Id": "86e2fb0b-30a8-4688-ad24-f7da9385c43c"
}
]
}
}
Loading

0 comments on commit bd358c7

Please sign in to comment.