0

我对单元测试非常熟悉,并且理解模拟和存根之间的区别。Roy Osherove 给出的最简单的解释是,所有的假货一开始都是存根,直到你反对它们,然后它们就是模拟物。

再一次,我明白了。我的问题是“使用单个假实例作为模拟和存根是错误的吗?以 Rhino Mocks 文档中的以下示例 ( http://ayende.com/wiki/Rhino+Mocks+3.5.ashx )

public void When_user_forgot_password_should_save_user()
{
  var mockUserRepository = MockRepository.GenerateMock<IUserRepository>();
  var stubbedSmsSender = MockRepository.GenerateStub<ISmsSender>();

  var theUser = new User{HashedPassword = "this is not hashed password"};    

  mockUserRepository.Stub(x => x.GetUserByName("ayende")).Return(theUser);

  mockUserRepository.Expect( x => x.Save(theUser) );

  var controllerUnderTest = new LoginController(mockUserRepository, stubbedSmsSender);

  controllerUnderTest.ForgotMyPassword("ayende");

  mockUserRepository.VerifyAllExpectations();
}

您会注意到 mockUserRepository 以 mock 一词命名并调用 GenerateMock 工厂,因为在代码的更下方,mockUserRepository 为其建立了行为预期,最终对行为的预期得到验证。很好,但在此过程中,mockUserRepository 正在调用它的 Stub() 方法来“可以”通过对同一对象的 GetUserByName() 调用返回的数据。

显然,这个例子展示了使用显式命名和声明的模拟作为模拟和存根。回到 Roy Osherove 的定义,即所有假货都是存根,直到你反对它们,我被迫相信使用假货作为模拟和存根(虽然肯定有效)是不好的做法。

有谁知道这样做是否有判决?

4

1 回答 1

0

我真的,真的不遵循你的逻辑。如果每个模拟都是一个存根,并且您同意这一点,那么将单个实例用作模拟和存根怎么可能是错误的。您别无选择:模拟是存根。每次你将它用作模拟时,你也将它用作存根。为了能够验证已调用模拟,必须已调用模拟。如果它被调用了,那么它在被调用的时候一定做了一些事情(即返回一个特定的值抛出一个异常)。为了能够让它返回一些东西,你必须把它存根。

顺便说一句,大多数时候,被测组件使用给定协作者的一个实例,而不是两个。很明显,您需要存根该实例。为了验证这个实例上的交互,存根必须成为一个模拟。因此,您必须将它用作模拟和存根。

于 2015-09-20T18:58:42.643 回答