我最近加入了一家他们使用TDD的公司,但我还是不太清楚,例如,我们有一个测试:
[TestMethod]
public void ShouldReturnGameIsRunning()
{
var game = new Mock<IGame>();
game.Setup(g => g.IsRunning).Returns(true);
Assert.IsTrue(game.Object.IsRunning);
}
这样做的目的是什么?据我了解,这没有测试任何东西!我这么说是因为它在模拟一个接口(interface),并且说,为 IsRunning 返回 true,它永远不会返回不同的值...
我可能想错了,因为每个人都说这是一个很好的做法等等......或者这个测试是错误的?
最佳答案
此测试正在执行一个接口(interface),并验证该接口(interface)是否公开了一个名为 IsRunning
的 bool getter。
这个测试可能是在 interface
存在之前编写的,并且可能远早于 IGame
的任何具体类存在之前。我想,如果该项目具有任何成熟度,则还有其他测试可以执行实际实现并验证该级别的行为,并且可能在更传统的孤立主义环境中使用模拟而不是 stub 理论形状。
这类测试的值(value)在于它迫使人们思考将如何使用形状或物体。类似于“我还不知道游戏要做什么,但我知道我想检查它是否正在运行……”。因此,这种测试方式更多地是为了插入设计决策,以及验证行为。
这不是地球上最有值(value)的测试,但在我看来达到了它的目的。
编辑:我昨晚在火车上打字时,但我想直接在答案中解决 Andrew Whitaker 的评论。
有人可能会争辩说,接口(interface)本身的签名足以执行所需的契约(Contract)。然而,这实际上取决于您如何处理接口(interface)以及最终如何验证您尝试测试的系统。
将此功能明确声明为测试可能具有实际值(value)。您正在明确验证这是 IGame
所需的功能。
让我们来看一个用例,假设作为一名设计师,您知道您想要为 IsRunning
公开一个公共(public) getter,因此您将其添加到界面中。但是假设另一个开发人员得到这个并看到一个属性,但在代码的其他任何地方看不到它的任何用法,人们可能会认为它有资格被删除(或代码腐烂删除,这通常是一件好事) 没有伤害。然而,这个测试的存在明确说明了这个属性应该存在。
如果没有这个测试,开发人员可以修改接口(interface),放弃实现,项目仍然可以正确编译和运行。直到很久以后,才会有人注意到界面已更改。
使用此测试,即使看起来好像没有人在使用它,您的测试套件也会失败。测试的 self 记录性质告诉您 ShouldReturnGameIsRunning()
,如果 IGame
确实暴露了一个 IsRunning
,它至少应该引发对话> setter/getter 。
关于c# - 为什么这个特定的测试可能有用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8394583/