上下求索

The Difference Between Mocks and Stubs

上一篇 / 下一篇  2010-09-15 16:04:00

Mocks Aren't Stubs(Martin Fowler)

http://www.martinfowler.com/articles/mocksArentStubs.html#TheDifferenceBetweenMocksAndStubs

The Difference Between Mocks and Stubs

When they were first introduced, many people easily confused mock objects with the common testing notion of using stubs. Since then it seems people have better understood the differences (and I hope the earlier version of this paper helped). However to fully understand the way people use mocks it is important to understand mocks and other kinds of test doubles. ("doubles"? Don't worry if this is a new term to you, wait a few paragraphs and all will be clear.)

When you're doing testing like this, you're focusing on one element of the software at a time -hence the common term unit testing. The problem is that to make a single unit work, you often need other units - hence the need for some kind of warehouse in our example.

In the two styles of testing I've shown above, the first case uses a real warehouse object and the second case uses a mock warehouse, which of course isn't a real warehouse object. Using mocks is one way to not use a real warehouse in the test, but there are other forms of unreal objects used in testing like this.

The vocabulary for talking about this soon gets messy - all sorts of words are used: stub, mock, fake, dummy. For this article I'm going to follow the vocabulary of Gerard Meszaros's book. It's not what everyone uses, but I think it's a good vocabulary and since it's my essay I get to pick which words to use.

Meszaros uses the termTest Doubleas the generic term for any kind of pretend object used in place of a real object for testing purposes. The name comes from the notion of a Stunt Double in movies. (One of his aims was to avoid using any name that was already widely used.) Meszaros then defined four particular kinds of double:

  • Dummyobjects are passed around but never actually used. Usually they are just used to fill parameter lists.
  • Fakeobjects actually have working implementations, but usually take some shortcut which makes them not suitable for production (anin memory databaseis a good example).
  • Stubsprovide 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'.
  • Mocksare what we are talking about here: objects pre-programmed with expectations which form. a specification of the calls they are expected to receive.

Of these kinds of doubles, only mocks insist upon behavior. verification. The other doubles can, and usually do, use state verification. Mocks actually do behave like other doubles during the exercise phase, as they need to make the SUT believe it's talking with its real collaborators - but mocks differ in the setup and the verification phases.

To explore test doubles a bit more, we need to extend our example. Many people only use a test double if the real object is awkward to work with. A more common case for a test double would be if we said that we wanted to send an email message if we failed to fill an order. The problem is that we don't want to send actual email messages out to customers during testing. So instead we create a test double of our email system, one that we can control and manipulate.

Here we can begin to see the difference between mocks and stubs. If we were writing a test for this mailing behavior, we might write a simple stub like this.

public interface MailService {
  public void send (Message msg);
}
public class MailServiceStub implements MailService {
  private List<Message> messages = new ArrayList<Message>();
  public void send (Message msg) {
    messages.add(msg);
  }
  public int numberSent() {
    return messages.size();
  }
}

We can then use state verification on the stub like this.

class OrderStateTester...
  public void testOrderSendsMailIfUnfilled() {
    Order rder = new Order(TALISKER, 51);
    MailServiceStub mailer = new MailServiceStub();
    order.setMailer(mailer);
    order.fill(warehouse);
    assertEquals(1, mailer.numberSent());
  }

Of course this is a very simple test - only that a message has been sent. We've not tested it was send to the right person, or with the right contents, but it will do to illustrate the point.

Using mocks this test would look quite different.

class OrderInteractionTester...
  public void testOrderSendsMailIfUnfilled() {
    Order rder = new Order(TALISKER, 51);
    Mock warehouse = mock(Warehouse.class);
    Mock mailer = mock(MailService.class);
    order.setMailer((MailService) mailer.proxy());

    mailer.expects(once()).method("send");
    warehouse.expects(once()).method("hasInventory")
      .withAnyArguments()
      .will(returnValue(false));

    order.fill((Warehouse) warehouse.proxy());
  }
}

In both cases I'm using a test double instead of the real mail service. There is a difference in that the stub uses state verification while the mock uses behavior. verification.

In order to use state verification on the stub, I need to make some extra methods on the stub to help with verification. As a result the stub implementsMailServicebut adds extra test methods.

Mock objects always use behavior. verification, a stub can go either way. Meszaros refers to stubs that use behavior. verification as a Test Spy. The difference is in how exactly the double runs and verifies and I'll leave that for you to explore on your own.

Junit in Action

stub这种机制是用来模拟可能存在或还没完成的真实代码所产生的行为。它使你能顺利的测试系统的一部分,而无需考虑其他部分是否可行。通常stub不会改变你测试的代码,只是加以适配以提供无缝的整合。

stub定义——stub是代码的一部分。在运行时我们用stub来代替真正代码,忽略调用代码的实现。目的是用一个简单一点的行为替换一个复杂的行为,从而允许独立地测试代码的一部分。

stub特点——stub的实现通常比较复杂,难以编写,尤其当仿真的系统很复杂的时候;一般而言,stub更适合替换代码中粗粒度的部分,通常会愿意用stub来替换成熟的外部系统,如文件系统、数据库、到服务器的连接等等。

Mock是使用来代替与你的代码协作的对象,从而提供了隔离层。从这个意义上来说,它跟stub类似,但相似之处也仅限于此,mock不实现任何逻辑,它只是传递由你的测试设置好的结果。

Mock技术能够提供更精细的控制,能够更完备地测试对象的行为。适合细粒度的测试。

很微妙的区别,很多时候英语对这些理性概念的术语会区分的更细致,而我们中文则很难找出好的翻译去区分stub和mock的概念。


TAG: Mock mock stub

 

评分:0

我来说两句

我的栏目

日历

« 2024-04-22  
 123456
78910111213
14151617181920
21222324252627
282930    

数据统计

  • 访问量: 126778
  • 日志数: 65
  • 建立时间: 2009-06-24
  • 更新时间: 2013-11-01

RSS订阅

Open Toolbar