10

Moq用来测试一些 void 方法的行为。MockBehaviour.Strict必须在Arrange步骤中指定使用对模拟的每个调用。这导致许多测试没有任何Assert(或验证)步骤。通过条件只是测试运行没有引发异常。我错过了什么吗?Arrange, Act, Assert使用严格的模拟时模式是否不合适?是否有更语义化的方式来布局这些测试?

一个简单的例子......

[TestClass]
public void DeleteUser_ShouldCallDeleteOnRepository()
{
    // Arrange
    var userRepository = new Mock<IUserRepository>(MockBehavior.Strict);

    int userId = 9;
    userRepository.Setup(x => x.Delete(userId));

    var controller = new UserController(userRepository.Object);

    // Act
    controller.DeleteUser(userId);

    // Assert
    // ...?
}
4

1 回答 1

24

您的模拟正在取代合作者。理想情况下,它会做以下两件事之一:

  • 提供信息或数据
  • 做一份工作

当 mock 提供信息或数据时,这应该是stub就足够了。您可以将模拟的返回值设置为所需的信息。这应该是Arrange的一部分。

当 mock 正在做一个工作时,可以验证委托。这就是你有Assert的原因。

您对严格交互所做的是确保每次交互都是预期的,基本上是说,“这就是我期望发生的事情,如果发生其他任何事情都是错误的。” 这是一种与 Act、Arrange、Assert 不同的测试,它说:“在这种情况下,当我做这些事情时,我应该得到这个结果。”

使用“漂亮”的模拟,您只需要担心您感兴趣的交互。因此,例如,如果我是一名控制器并且我正在一个存储库中查找一些信息,并使用验证器对其进行验证,然后将结果保存在另一个存储库中,我可能有几个测试:

  • 用于检查我是否根据正确的信息进行验证
  • 一个检查我如何响应不正确的验证
  • 还有一个检查我是否保存了该项目。

使用严格的模拟,您必须完成所有期望,即使您感兴趣的只是“保存”。通过使用漂亮的模拟,我们可以拆分行为的不同方面,并在每个测试中只关注其中一个方面。

作为额外的奖励,漂亮的模拟允许您执行以下操作:

  • 给定一个上下文
  • 当这个事件发生时
  • 那么这个结果应该会发生

而严格的模拟让你这样做:

  • 给定一个上下文
  • 期待一些事情发生
  • 当我执行一个事件时
  • 然后回去看看结果应该是什么。

其中第一个通常被认为更具可读性。

于 2011-12-22T17:34:33.747 回答