c# - xUnit 测试引擎的 InlineDataAttribute + 可选方法参数

标签 c# unit-testing optional-parameters xunit optional-arguments

如果不在 InlineDataAttribute 中指定可选参数值,是否可以使 xUnit 测试工作?

例子:

[Theory]
[InlineData(1, true)] // works
[InlineData(2)]       // error
void Test(int num, bool fast=true){}

最佳答案

是的。有很多方法可以通过重新定义一些原始的 xunit 属性来实现。

下面的代码就是其中之一,它会给你一些想法。

[AttributeUsage(AttributeTargets.Method, AllowMultiple = true, Inherited = true)]
public class OptionalTheoryAttribute : TheoryAttribute
{
    protected override IEnumerable<ITestCommand> EnumerateTestCommands(IMethodInfo method)
    {
        var result = (List<ITestCommand>)base.EnumerateTestCommands(method);

        try
        {
            return TransferToSupportOptional(result, method);
        }
        catch (Exception ex)
        {
            result.Clear();
            result.Add(new LambdaTestCommand(method, () =>
                {
                    throw new InvalidOperationException(
                        String.Format("An exception was thrown while getting data for theory {0}.{1}:\r\n{2}",
                            method.TypeName, method.Name, ex)
                        );
                }));
        }
        return result;
    }

    private static IEnumerable<ITestCommand> TransferToSupportOptional(
        IEnumerable<ITestCommand> testCommands, IMethodInfo method)
    {
        var parameterInfos = method.MethodInfo.GetParameters();
        testCommands.OfType<TheoryCommand>().ToList().ForEach(
            testCommand => typeof(TheoryCommand)
                               .GetProperty("Parameters")
                               .SetValue(testCommand, GetParameterValues(testCommand, parameterInfos)));
        return testCommands;
    }

    private static object[] GetParameterValues(TheoryCommand testCommand, ParameterInfo[] parameterInfos)
    {
        var specifiedValues = testCommand.Parameters;
        var optionalValues = GetOptionalValues(testCommand, parameterInfos);

        return specifiedValues.Concat(optionalValues).ToArray();
    }

    private static IEnumerable<object> GetOptionalValues(TheoryCommand command, ParameterInfo[] parameterInfos)
    {
        return Enumerable.Range(command.Parameters.Length, parameterInfos.Length - command.Parameters.Length)
                         .ToList().Select(i =>
                             {
                                 EnsureIsOptional(parameterInfos[i]);
                                 return Type.Missing;
                             });
    }

    private static void EnsureIsOptional(ParameterInfo parameterInfo)
    {
        if (!parameterInfo.IsOptional)
        {
            throw new ArgumentException(string.Format(
                "The parameter '{0}' should be optional or specified from data attribute.",
                parameterInfo));
        }
    }
}

internal class LambdaTestCommand : TestCommand
{
    private readonly Assert.ThrowsDelegate lambda;

    public LambdaTestCommand(IMethodInfo method, Assert.ThrowsDelegate lambda)
        : base(method, null, 0)
    {
        this.lambda = lambda;
    }

    public override bool ShouldCreateInstance
    {
        get
        {
            return false;
        }
    }

    public override MethodResult Execute(object testClass)
    {
        try
        {
            lambda();
            return new PassedResult(testMethod, DisplayName);
        }
        catch (Exception ex)
        {
            return new FailedResult(testMethod, ex, DisplayName);
        }
    }
}

public class OptionalTheoryTest
{
    [OptionalTheory]
    [InlineData(1)]
    [InlineData(1, true)]
    public void TestMethod(int num, bool fast = true)
    {
        // Arrange
        // Act
        // Assert
        Assert.Equal(1, num);
        Assert.True(fast);
    }
}

关于c# - xUnit 测试引擎的 InlineDataAttribute + 可选方法参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14818439/

相关文章:

c# - 远程进程执行

c# - 应用程序处于中断模式,aspnet core

eclipse - Eclipse 中的 PerlUnit

java - 安卓交互器测试

android - 如何在 android 中使用 groovy 制作 integrationTest 源集?

c# - 如何在 C# 中传递作为结构的可选参数

c# - 传递空数组作为可选参数的默认值

python - 如何使用装饰器为函数参数设置默认值?

c# - 什么技术允许在不更改 URL 的情况下更改页面内容?

c# - 为什么我这里有锁?