需要泛型类型时进行单元测试

Unit testing when generic type is needed

我有以下问题。我想测试通用 class MyClass<'T>。但是,我并不真正关心用于 T 的类型。 但是,当我在测试中创建 MyClass 的实例时,我需要指定 T 应该是什么。 我可以这样做:

var sut = new MyClass<Object>();

它当然有效,但是,我不喜欢专门放置对象,因为它向阅读此测试的人暗示对象类型在这里可能有些重要。

我喜欢 AutoFixture 使用的方法,其中每个值都是使用 fixture.Create<T>() 创建的,因为它向 reader 表明该值并不是很重要。例子:

[Fact]
public void IntroductoryTest()
{
    // Arrange
    Fixture fixture = new Fixture();

    int expectedNumber = fixture.Create<int>();
    MyClass sut = fixture.Create<MyClass>();
    // Act
    int result = sut.Echo(expectedNumber);
    // Assert
    Assert.Equal(expectedNumber, result);
}

在上面的代码中我们不关心数字,所以我们使用 AutoFixture 作为对需要一些数字这一事实的抽象。

是否有类似的解决方案,但关于与通用 classes 一起使用的类型?

类似于:var sut = MyClass<fixture.GenericType>(); 我在这里不关心实际类型是什么。进一步解释我的用例:我有用于注册 MyClass 的 AutoFac 模块。在我的测试中,我只想测试模块是否正确注册了 MyClass。对于该注册,我不想指定要用于 MyClass 的某些确切类型。可以是任何一个。

也许你可以定义一个基类型,比如 IBase,其中你所有的 T 类型都实现了 IBase (Class1<T> where T : IBase),然后你可以说 var sut = new MyClass<IBase>();

目前 AutoFixture 不支持非封闭泛型激活,不太可能有一天会改变。

首先是因为C#语言本身支持非封闭泛型,仅用于反射目的。您不能在不关闭特定 T 类型的情况下声明 MyClass<> 类型的变量。因此,即使 AutoFixture 替换类型并为您激活一个实例,也很难处理结果 - 如果您需要,您要么需要使用 object 类型的变量,要么依赖 covariance类型支持这一点。 None 这些选项看起来可用。

其次,任务本身非常艰巨,因为泛型类型可能有限制。有时约束会变得疯狂,例如具有循环依赖性:class MyClass<T1, T2> where T1 : T2 where T2 : IEnumerable<T1>AutoFixture.Idioms 库已经尝试为 GuardClauseAssertion 解决该问题,但成功了 is average。此功能需要动态类型生成(顺便说一句,并非所有平台都支持)和 Reflection.Emit API 的非常高级的用法,这使得它很难正确实现。