测试 class 没有泛型的简化

Test class simplification without generics

我有大量模型都实现了 IEquatable<T>,除了 SUT 类型之外,我还有几个看起来相似的测试 classes。这些测试验证了所有由被测模型实现的实现和其他一些常见方面。

使用抽象的通用测试 class 并没有取得多大的成就,我放弃了对运算符的编译时重载决议,而且我必须为每种类型实施派生测试 class。

使用 MemberData 属性有助于消除对派生测试 classes 的需要,但是对运算符的编译时重载解决方案仍然存在。

是否存在另一种方法,例如 InlineData 我在运算符上维护编译时重载决策并使用单个对象集合(无论它们是否为类型)来调用测试方法?

在下面的示例中,我使用 MemberData 但必须使用反射来调用 ==!= 运算符并且测试方法签名不是最佳的,因为它们未被使用(仅使用泛型类型参数)。

[Theory]
[MemberData(nameof(GetModelTypes))]
public void MyTest<T>(T _)
    where T : class, new()
{
    var fixture = new Fixture().Customize(new AutoMoqCustomization());
    // Add any known type customization's...

    T t = fixture.Create<T>();
    // Implement remaining generic test body.
}

public static IEnumerable<object[]> GetModelTypes() =>
{
    new object[] {new ModelA()},
    new object[] {new ModelB()},
    /* ... */
}

有谁知道一种方法可以让我维护一个对象集合并使用编译时重载解决方案进行测试?

首先,用一个单一的静态集合来测试不同的行为是一种自杀。不要自己开枪。其次,除了现在拥有 am 属性使您能够 运行 反射之外,您还不太清楚您要实现的目标。如果您的问题是关于将反射与泛型一起使用,那么它确实是可能的。查看类似 typeof(GenericType<>).MakeGenericType(...).

的内容

你可以write generic unit test classes with xUnit.net这样:

public abstract class ModelTests<T>
{
    [Fact]
    public void MyTest()
    {
        var fixture = new Fixture();
        var sut = fixture.Create<T>();

        // The rest of the test goes here...
    }

    // More tests go here...
}

public class ModelATests : ModelTests<ModelA> { }
public class ModelBTests : ModelTests<ModelB> { }

就是说,如果您有大量看起来相似的测试,可能值得研究 AutoFixture.Idioms,尤其是它的 IdiomaticAssertion 基础 class.