我可以将一个委托人传递给Xunit理论吗

问题描述

我对在多个类上重用测试理论感兴趣,特别是在需要相同测试的许多构造函数中。我最初的想法是使用委托来执行此功能

但是,我认为我可能正在尝试重新发明轮子,尽管C#具有某些功能,但我认为我正在尝试一种不合适的方法。是否存在使用比InlineData更正确的东西来支持这种事情的方法

InlineData似乎是用于注入输入的,因此我可以测试给定测试的许多示例。但是我可以为几种方法提供几个变量并进行测试^ x而不是* x

[Theory]
[InlineData(input => new ConcreteConstructor(input)) ]
public void Constructor_Should_Not_Throw_Expection (Action<string>)
{
  constructor("SomeString");            
}

N.B我认为在这种情况下我应该使用Func作为返回对象。无论如何,我怀疑这是完全错误方法,因此不是主要考虑因素。

解决方法

public static IEnumerable<object[]> TestData()
{
  Action<string> a1 = input => new ConcreteConstructor(input);
  yield return new object[] { a1 };
  Action<string> a2 = input => new AnotherConstructor(input);
  yield return new object[] { a2 };
}

[Theory]
[MemberData(nameof(TestData))]
public void Constructor_Should_Not_Throw_Expection(Action<string> constructor)
{
  constructor("SomeString");
}
,

一种继承了通用抽象类的解决方案:

abstract public class CommonTest_ConstructorShould
{   
        public abstract void Constructor(string input);

        [Fact]
        public void Constructor_Should_Not_Throw_Expection()
        {
            Constructor(System.IO.Directory.GetCurrentDirectory());
        }

        [Fact]
        public void Constructor_Should_Throw_Exception()
        {
            Assert.Throws<ArgumentException>(() => Constructor("/PPPPPPPPPPPPPPPPPPPPPPP"));
        }
    }

    public class LunarCalendarClient_ConstructorShould : LocalJsonClient_ConstructorShould
    {   
        override public void Constructor(string input){
            new ConcreteClass(input);
        }
    }
,

感谢 Yevheniy Tymchishinanswer,我想添加其他方法,以防万一有人想添加 delagate 而不在 yield return 之外声明新对象。

static IEnumerable<object[]> Data
{
    get 
    {
        //Yevheniy's approach
        Action<string> a1 = input => Construct(input);
        yield return new object[] { a1 };

        //new approach with hidden parameter
        yield return new object[] {new Action<string> (Construct)};
        
        //same but with exposed parameter syntax
        yield return new object[] {new Action<string> ((input) => Construct(input))};
    }
}

它们三个都做完全一样的事情,只是语法不同,相同的逻辑适用于任何其他委托类型(func 或其他)