使用 Mocks 验证依赖项调用时的 TDD Arrange Act Assert 模式
我正在使用 Moq
来测试某些 void 方法的行为。使用 MockBehaviour.Strict
对模拟的每次调用都必须在 Arrange
步骤中指定。这导致许多测试没有任何断言(或验证)步骤。通过的条件很简单,就是测试运行时没有抛出异常。我错过了什么吗?使用严格模拟时,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
// ...?
}
I'm using Moq
to test behaviour of some void methods. Using MockBehaviour.Strict
every call to the mock must be specified during Arrange
step. This is resulting in a lot of tests not having any Assert
(or Verify) step. The pass condition is simply that the test ran without throwing an exception. Am I missing something? Is the Arrange, Act, Assert
pattern unsuitable when using strict mocks? Is there a more semantic way to layout these tests?
A trivial made up example...
[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
// ...?
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
你的模拟正在取代合作者。理想情况下,它会执行以下两件事之一:
当模拟提供信息或数据时,它应该是一个存根就足够了。您可以将mock的返回值设置为所需的信息。这应该是安排的一部分。
当模拟正在执行工作时,可以验证委托。。这就是为什么你有断言。
你在严格交互中所做的就是确保每一次交互都是预期的,基本上是说,“这就是我期望发生的事情,如果发生其他任何事情,那就是错误的。”这是与“行动”、“安排”、“断言”不同的测试,“在这种情况下,当我做这些事情时,我应该得到这个结果”。
通过“良好”的模拟,您只需要担心您感兴趣的交互。因此,例如,如果我是一名控制器,并且我正在一个存储库中查找一些信息,并使用验证器对其进行验证,然后将结果保存在另一个存储库中,我可能需要进行多项测试:
通过严格的模拟,您必须满足所有期望,即使您感兴趣的只是“保存”。通过使用一个很好的模拟,我们可以分解行为的不同方面,并在每个测试中只关注其中一个方面。
作为额外的好处,好的模拟允许你做:
而严格的模拟让你做:
第一个通常被认为更具可读性。
Your mock is taking the place of a collaborator. It's ideally doing one of two things:
When the mock is providing information or data, it's enough that this should be a stub. You can set up the return value of the mock to the information required. This should be part of Arrange.
When the mock is doing a job, the delegation can be verified. This is why you have Assert.
What you're doing with the strict interaction is ensuring that every single interaction is expected, basically saying, "Here's what I expect to happen, and if anything else happens it's wrong." This is a different kind of testing to Act, Arrange, Assert, which says, "In this context, when I do this stuff, then I should get this outcome."
With a "nice" mock, you only need to worry about the interactions you're interested in. So, for instance, if I'm a controller and I'm looking up some information in one repository, validating it with a validator, then saving the result in another repository, I might have several tests:
With the strict mock, you have to do all the expectations, even if all you're interested in is the "save". By using a nice mock, we can split up the different aspects of behavior and only focus on one of them in each test.
As an additional bonus, nice mocks allow you to do:
Whereas strict mocks make you do:
The first of these is generally considered more readable.