【问题标题】:How to write a unit test for "T must be a reference type"?如何为“T 必须是引用类型”编写单元测试?
【发布时间】:2010-10-27 15:14:07
【问题描述】:

考虑:

class MyClass<T> where T : class
{
}

在这种情况下,where 子句强制说明 MyClass 只是引用类型的泛型。

理想情况下,我应该有一个单元测试来测试这个规范。但是,这个单元测试显然不起作用,但它解释了我想要完成的事情:

[Test]
[DoesNotCompile()]
public void T_must_be_a_reference_type()
{
    var test = new MyClass<int>();
}

我可以做些什么来测试通过不允许代码编译来实现的规范?

编辑

更多信息:好的,所以我这样做的理由(哈哈)是我一直在遵循 TDD 方法,在这种方法中你不能编写任何代码,除非你有一个失败的单元测试。假设你有这个:

class MyClass<T> { }

除非 T 是一个类,否则你可以编写什么测试会失败? default(T) == null 之类的东西?

进一步编辑

因此,在对此进行“根本原因分析”之后,问题是我以隐含的方式依赖 default(T) 在此类的消费者中成为 null。我能够将该消费者代码重构到另一个类中,并在那里指定一个泛型类型限制(将其限制为class),如果有人要删除我在上面谈论的类的限制,这实际上会使该代码无法编译.

【问题讨论】:

  • 你为什么不对这个类命名为MyClass进行单元测试?
  • @SLaks:技术上 var test = new MyClass();会测试,不是吗?
  • 我认为@SLaks 正在使用讽刺来证明您不需要测试编译器的观点......这是微软的工作。
  • @TheCloudlessSky:我的意思是,如果您遵循 TDD,除非您编写了第一个单元测试,否则您不会创建该类,除非您使用一个不存在的类的名称。所以是的,你的第一个单元测试隐式地测试了类的名称。

标签: c# unit-testing tdd


【解决方案1】:

为什么需要为此进行单元测试?您是否为诸如

之类的方法编写单元测试
public void Foo(string x)

检查它只能接受字符串,不能接受整数?如果不是,您认为有什么不同?

编辑:只是稍微不那么异想天开:在这种情况下,规范由 声明 验证。测试通常应该测试行为。这是我喜欢代码合同的一件事:我觉得没有必要对合同进行单元测试,除非它们表达了一些复杂的东西——在这种情况下,我要测试的是复杂性,而不是“强制执行合同”位.

编辑:回答问题编辑:

除非 T 是一个类,否则你可以编写什么测试会失败?

可以写这样的:

Type definition = typeof(MyClass<>);
Assert.Throws<ArgumentException>(() => definition.MakeGenericType(typeof(int)));

但是,这似乎违背了测试的真正目的......

【讨论】:

  • 好吧,我正在尝试让我的单元测试包含被测单元的所有规范。
  • @Jon Funny,我们想到了完全相同的例子
  • @Scott Whitlock - 但只是代码编译你的测试。
  • @Scott:我认为 TDD 不应该要求这个。同样,您不会编写测试来确保您不能传递无效参数。您的测试推动了设计的积极 方面(“我可以使用引用类型参数”),但不一定是消极 方面。归根结底,所有测试都应该是务实的 - 但测试编译器不是实用地利用您的时间,IMO。
  • 好的,你解释了为什么我不需要测试,并且给了我一个可行的答案,+2 给你! :
【解决方案2】:

您不应该测试编译器是否能正常工作。如果您在代码中指定它,这就足够了。从代码的角度来看,这和这个大致相同:

[Test]
public void Test_whether_add_works()
{
    int i = 1 + 2;

    Assert.AreEqual(3, i);
}

【讨论】:

  • '[测试] public void Running1984() { Assert.AreEqual(5, 2 + 2); }'
【解决方案3】:

这是一个很好的问题!非常同意您的测试驱动方法。您正在努力解决的问题实际上是两种范式的冲突。旧范式应该使用数学证明程序是正确的而不运行它们(这是我们职业在数学方面的祖先的遗产),而新范式应该通过执行示例用例(即测试)来证明编程是正确的。所以你要尝试的是将新范式的实践应用到旧范式的工件上,这当然不会真正起作用……

有关类型和测试的二分法的更多信息,请参阅 Chris Smith 的这篇优秀文章,http://web.archive.org/web/20080822101209/http://www.pphsg.org/cdsmith/types.html

【讨论】:

    【解决方案4】:

    您是否正在编写正确的单元测试?看起来你要测试 C# 编译器,而不是你的代码。

    【讨论】:

      猜你喜欢
      • 2019-12-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-03
      • 2016-09-08
      • 1970-01-01
      相关资源
      最近更新 更多