Методы тестирования NUnit на самом деле могут быть общими, если аргументы универсального типа могут быть выведены из параметров:
[TestCase(42)]
[TestCase("string")]
[TestCase(double.Epsilon)]
public void GenericTest<T>(T instance)
{
Console.WriteLine(instance);
}
![NUnit Generic Test](https://i.stack.imgur.com/mfHXY.png)
Если обобщенные аргументы не могут быть выведены, исполнитель теста не будет иметь понятия, как разрешить аргументы типа:
[TestCase(42)]
[TestCase("string")]
[TestCase(double.Epsilon)]
public void GenericTest<T>(object instance)
{
Console.WriteLine(instance);
}
![NUnit Generic Test Fail](https://i.stack.imgur.com/S5lcT.png)
Но в этом случае вы можете реализовать пользовательский атрибут:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TestCaseGenericAttribute : TestCaseAttribute, ITestBuilder
{
public TestCaseGenericAttribute(params object[] arguments)
: base(arguments)
{
}
public Type[] TypeArguments { get; set; }
IEnumerable<TestMethod> ITestBuilder.BuildFrom(IMethodInfo method, Test suite)
{
if (!method.IsGenericMethodDefinition)
return base.BuildFrom(method, suite);
if (TypeArguments == null || TypeArguments.Length != method.GetGenericArguments().Length)
{
var parms = new TestCaseParameters { RunState = RunState.NotRunnable };
parms.Properties.Set("_SKIPREASON", $"{nameof(TypeArguments)} should have {method.GetGenericArguments().Length} elements");
return new[] { new NUnitTestCaseBuilder().BuildTestMethod(method, suite, parms) };
}
var genMethod = method.MakeGenericMethod(TypeArguments);
return base.BuildFrom(genMethod, suite);
}
}
Использование:
[TestCaseGeneric("Some response", TypeArguments = new[] { typeof(IMyInterface), typeof(MyConcreteClass) }]
public void MyMethod_GenericCall_MakesGenericCall<T1, T2>(string expectedResponse)
{
// whatever
}
и аналогичная настройка для TestCaseSourceAttribute
:
[AttributeUsage(AttributeTargets.Method, AllowMultiple = true)]
public class TestCaseSourceGenericAttribute : TestCaseSourceAttribute, ITestBuilder
{
public TestCaseSourceGenericAttribute(string sourceName)
: base(sourceName)
{
}
public Type[] TypeArguments { get; set; }
IEnumerable<TestMethod> ITestBuilder.BuildFrom(IMethodInfo method, Test suite)
{
if (!method.IsGenericMethodDefinition)
return base.BuildFrom(method, suite);
if (TypeArguments == null || TypeArguments.Length != method.GetGenericArguments().Length)
{
var parms = new TestCaseParameters { RunState = RunState.NotRunnable };
parms.Properties.Set("_SKIPREASON", $"{nameof(TypeArguments)} should have {method.GetGenericArguments().Length} elements");
return new[] { new NUnitTestCaseBuilder().BuildTestMethod(method, suite, parms) };
}
var genMethod = method.MakeGenericMethod(TypeArguments);
return base.BuildFrom(genMethod, suite);
}
}
Использование:
[TestCaseSourceGeneric(nameof(mySource)), TypeArguments = new[] { typeof(IMyInterface), typeof(MyConcreteClass) }]