From: Nat Pryce Date: 2001-08-31T09:00:55+09:00 Subject: [ruby-talk:20593] Re: To those who want abstract classes in Ruby > I'm sorry, I've never heard the term `mock object' before, but > I think I can guess it out. To be metaphorical: A mock object > seems to be something like a holo object. If you know Star Trek you > will also know that there is a special region called the holo deck. > Within this holo deck you can tell the computer to generate sceneries > and characters at will, and the computer will generate holo objects > according to the `classes' it has got in its memory. After this > generation you can act with the holos just as you would act with the > real buildings, countries, people, tools -- and wouldn't notice any > difference. > > I remember that Jordi LaForge had his best ideas about technical > problems when he was simulating them within the holo deck. > > Is it this what mock objects are all about? That's a good analogy. A mock object is an implementation of the interface of an object that is used by the class being tested. E.g. if a class being tested uses a database connection, you would mock up the database connection in order to test the class rather than connect to a real database. Why? There are several advantages. 1) It's more convenient than setting up a "real" test environment; e.g. a database host and server install, networking, etc. 2) You can guarantee predetermined responses from the mock object, and so test the behaviour of your class without worrying about unexpected errors. E.g. someone might unplug the database server in your test environment which would cause unexpected test failures unrelated to the features being tested. 3) You can make the mock object throw exceptions, to test how the client class acts in the face of errors. You would be amazed how much code is only tested through the success control paths. So far a mock object sounds the same as a stub. However, the mock objects technique extends stubs by executing tests in the mock object itself. The writers of the mock object paper call this "endotesting" because you are inserting tests into the implementation of a class, rather than testing only by probing it from the outside. E.g. 4) For each test, you can test that the class makes the expected sequence of method calls, and passes in the expected parameters. These are termed "expectations". 5) You can test that the class meets the preconditions of the objects it uses by asserting those preconditions in the mock object. Normal unit tests only check the postconditions and invariants of the class under test, not that it meets preconditions required of it by other parts of the system. 6) You can encapsulate a mocked protocol -- e.g. preconditions and valid sequences of method calls -- as a reusable class that can be parameterised by expectations. More info about mock objects can be found at http://www.mockobjects.com/. I have written Ruby/Mock, a package that provides a convenient way of implementing mock objects using a generic Mock class. A test uses closures to define the expectations of a mock object and can encapsulate protocols into reusable mock-object classes. I have put it online at http://www.b13media.com/dev/ruby/mock.html. Cheers, Nat.