What does your code do? Or pretend to do?

What code does

Code does:

Sequencing: performing actions in a certain order.
Logic: performing actions according to logic.
Transformation: changing data from one form to another.
Utility: getting some data from some other data, eg: "cat,dog,horse".split(",").
State: removing from, adding to or changing state.
Hardware interaction: keyboards, screens, ports, hard disks, etc.
Library interaction: talking to libraries, systems or drivers that encapsulate the above.

If your method or class does more than one of these things, such as performing transformations in a particular sequence, then maybe that’s a good place to start refactoring new methods. Or new classes.

Disclaimers:
The list may not be complete; if you can think of anything else that code does, please let me know!
I’m sure this list isn’t original, but I’m not sure where I got it from. My terminology may not be standard.

Pretending to do it

This list was prompted by Simon’s post on the Rules of Engagement for using mocks (or not). I agree with Simon that:

  1. For every expectation set upon a mock, you must write a corresponding test to verify that the expectation is a realistic one.
  2. Every time you change the behaviour of an object, revisit each and every test that mocks out this behaviour and verify that the expectations used are still valid

Sometimes, though, we really care about the interaction. Not all of the actions above can be defined using stubs. For this reason, and in the spirit of Sun Tzu, who said something like “Win the war before you fight it,” I hereby present my own Rules of Engagement.

  1. Every aspect of behaviour should have a reason for being there. If the code under test is the customer of the mocked or stubbed class, you can define the behaviour of the mocked class.
  2. For every behaviour you add to a class you’re mocking, write an empty test to define that behaviour. For instance, if I mock out a Sheep, I might write:
    public class SheepTest extends TestCase {
        public void testShouldEatAnyAvailableGrass() {
            //TODO
            // or fail("TODO"); if you want to remember to do it before you check in
        }
    }
    

    I can do this before I code my sheep, and implement the real class when I’m done with its customer. This helps deal with Simon’s rule 1.

  3. Make mocked classes behave predictably wherever possible, eg: don’t throw exceptions for things you expect to happen under normal operation, and don’t return null if you don’t have to.
  4. If you change the behaviour of a class which is being mocked out elsewhere, you will (ought to!) break the test. If this happens, consider whether the behaviour as defined is inappropriate. If so, see Simon’s rule 2.
  5. It’s much, much easier to deal with mocks and interactions if the classes under test, and the classes being mocked, aren’t trying to do too much. See the first bit of this post.

I really love mocks. šŸ™‚

This entry was posted in Uncategorized. Bookmark the permalink.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s