I was reading Andrew Lock's excellent blog post about Creating parameterised tests in xUnit when I remembered something I wrote a while back that has proven to be quite useful.
The code in question allows you to use embedded resources with xUnit's theory concept
(which is similar to a TestCase
in NUnit).
using System;
using System.Collections.Generic;
using System.IO;
using System.Reflection;
using Xunit.Sdk;
namespace MyProject.Tests
{
public sealed class EmbeddedResourceDataAttribute : DataAttribute
{
private readonly string[] _args;
public EmbeddedResourceDataAttribute(params string[] args)
{
_args = args;
}
public override IEnumerable<object[]> GetData(MethodInfo testMethod)
{
var result = new object[_args.Length];
for (var index = 0; index < _args.Length; index++)
{
result[index] = ReadManifestData(_args[index]);
}
return new[] { result };
}
public static string ReadManifestData(string resourceName)
{
var assembly = typeof(EmbeddedResourceDataAttribute).GetTypeInfo().Assembly;
resourceName = resourceName.Replace("/", ".");
using (var stream = assembly.GetManifestResourceStream(resourceName))
{
if (stream == null)
{
throw new InvalidOperationException("Could not load manifest resource stream.");
}
using (var reader = new StreamReader(stream))
{
return reader.ReadToEnd();
}
}
}
}
}
You can now use embedded resources in your tests like this:
namespace MyProject.Tests
{
public sealed class JediCouncilFixture
{
[Theory]
[EmbeddedResourceData("MyProject.Tests/Data/File.json")]
public void Should_Return_Expected_Advice_From_Jedi_Council(string json)
{
// Given
var expected = JsonConvert.DeserializeObject<Advice>(json);
// When
var result = JediCouncil.AskForAdvice();
// Then
Assert.Equal(expected, result, new AdviceComparer());
}
}
}