我读过各种关于测试中模仿和存根的文章,包括Martin Fowler的《Mocks Aren't Stubs》,但我仍然不理解其中的区别。


当前回答

我喜欢Roy Osherove的解释。

创建的每个类或对象都是Fake。如果您验证它是一个Mock 反对它的呼声。否则就是存根。

其他回答

我偶然看到了《小嘲笑者鲍勃叔叔》的一篇有趣的文章。它以一种非常容易理解的方式解释了所有的术语,因此对初学者很有用。Martin fowler的文章很难读,尤其是对于像我这样的初学者。

Mock——Mock拦截对一个方法或函数的调用(或者像模拟类那样的一组方法和函数)。它不是该方法或函数的替代品。在那次拦截中,mock可以做任何它想做的事情,比如记录输入和输出,决定短路调用,更改返回值,等等。

存根——存根是一个有效的方法或函数(或一组方法和函数,就像存根类一样)的完整工作实现,它与它存根的方法、函数或一组方法和函数具有相同的接口/签名。stub实现通常只会做在单元测试上下文中可以接受的事情,这意味着它不会做IO,同时模仿它要stub的东西的行为。

A fake is a generic term that can be used to describe either a stub or a mock object (handwritten or otherwise), because they both look like the real object. Whether a fake is a stub or a mock depends on how it’s used in the current test. If it’s used to check an interaction (asserted against), it’s a mock object. Otherwise, it’s a stub. Fakes makes sure test runs smoothly. It means that reader of your future test will understand what will be the behavior of the fake object, without needing to read its source code (without needing to depend on external resource). What does test run smoothly mean? Forexample in below code: public void Analyze(string filename) { if(filename.Length<8) { try { errorService.LogError("long file entered named:" + filename); } catch (Exception e) { mailService.SendEMail("admin@hotmail.com", "ErrorOnWebService", "someerror"); } } } You want to test mailService.SendEMail() method, to do that you need to simulate an Exception in you test method, so you just need to create a Fake Stub errorService class to simulate that result, then your test code will be able to test mailService.SendEMail() method. As you see you need to simulate a result which is from an another External Dependency ErrorService class.

Stubs vs. Mocks Stubs provide specific answers to methods calls ex: myStubbedService.getValues() just return a String needed by the code under test used by code under test to isolate it cannot fail test ex: myStubbedService.getValues() just returns the stubbed value often implement abstract methods Mocks "superset" of stubs; can assert that certain methods are called ex: verify that myMockedService.getValues() is called only once used to test behaviour of code under test can fail test ex: verify that myMockedService.getValues() was called once; verification fails, because myMockedService.getValues() was not called by my tested code often mocks interfaces

看了上面所有的解释,让我试着总结一下:

Stub:让测试运行的一段虚拟代码,但您并不关心它会发生什么。替代实际工作代码。 Mock:在测试中验证是否正确调用的一段虚拟代码。替代实际工作代码。 间谍:一段虚拟代码,用于拦截和验证对实际工作代码的某些调用,从而避免替换所有实际代码。