垫片和存根之间的区别

Difference between shims and stubs

任何人都可以非常清楚地告诉我单元测试期间 shimstub 之间的主要区别是什么?

我知道模拟对象,也读过 shim 和 stub,但仍然不清楚我应该在哪个上下文中使用 shim 或 stub。

让我引用 Martin Fowler 的文章 Mocks Aren't Stubs:

Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it 'sent', or maybe only how many messages it 'sent'.

Mocks are [...] objects pre-programmed with expectations which form a specification of the calls they are expected to receive.

因此,如果违反预期,模拟可以直接使测试失败。存根不会那样做。

Shims(或 Moles)与两者的不同之处在于它们可用于替换静态方法等硬编码依赖项。您应该避免使用 IMO 而更喜欢重构,这使得这些依赖项可以替换。请参阅 this thread 进行进一步讨论,尤其是 Jim Cooper 的回答。

作为一般指南,使用 stubs 进行 Visual Studio 解决方案中的调用,使用 shim 调用其他引用的程序集。这是因为在您自己的解决方案中,通过以存根要求的方式定义接口来解耦组件是一种很好的做法。但是 System.dll 等外部程序集通常不提供单独的接口定义,因此您必须改用 shims

很好reference

据我了解,不同之处在于模拟代码所在的位置或您模拟的代码部分(即 "where" 给出了区别)。所以我会把它写成:

You call Stub the part of your code which you mocked while it will be called Shim if you mock some external call.

  • "your code"为待测代码
  • "external call"是你的代码所依赖的依赖

我发现这个参考很好:My two cents on fakes, stubs, mocks, and shims 特别是部分“一般规则是利用存根进行内部调用,利用填充程序进行外部程序集。

垫片通常用于从您的解决方案外部的程序集提供模拟,而存根用于在您的解决方案中创建 类 的模拟。

存根示例

// Create the fake calculator:
ICalculator calculator = new Calculator.Fakes.StubICalculator()
{
// Define each method:
Add = (a,b) => { return 25; }
};

垫片示例

//Using shims to control the response to DateTime.Now
using (ShimsContext.Create())
{
// insert the delegate that returns call for DateTime.Now
System.Fakes.ShimDateTime.NowGet = () => new DateTime(2010, 1, 1);
MethodThatUsesDateTimeNow();
}

礼貌: 考试参考 70-486