The command pattern allows you to wrap a command inside an object so that you can pass it to another object to execute that object. We were using a simplified version of the pattern where we had a command interface that has an Execute method and a Results property to retrieve the results:
public interface ICommand
{
void Execute();
string Result{ get; }
}
Objects of this type are then passed in as an IList to a CommandExecutor that loops through the commands and calls Execute on each one:
public class CommandExecutor
{
public void Execute(IList commands)
{
// loop through the commands and
// call the command.Execute method
}
}
So we wanted to write a test that ensured that the Execute method was called on each command that we provided to the CommandExecutor. Initially we thought about sending through a concrete Command (say a ConcatenationCommand) and determining that the result was what we expected. However, this would have coupled our design to that particular Command - if we made a change to the results that returned we would have to update our tests. In this case we aren't concerned about the actual result, just that Execute is called on each command. The question was how can we test this behaviour without having to worry about a concrete Command or its result?
This is where Mock objects come in (see the original Mock paper or the Pragmatic Programmer's overview). They allow you to test the behaviour of an object rather than just its outcome. The idea is to create a 'fake' or stub object that validates the object was used in the way we expected. In our case we could create a MockCommand that derives from ICommand. We could provide a boolean property - ExecuteWasCalled - on the class that could be set inside the execute command.
public class MockCommand : ICommand
{
public bool ExecuteWasCalled;
public void Execute()
{ ExecuteWasCalled = true; }
public string Result { get { return "result"; }}
}
While this would work fine, since our needs are pretty simple in this case we could use NMock which provides a way of creating a DynamicMock object based on an Interface. The DynamicMock exposes a property that can set expectations about the behaviour of an object, such as a particular method being called. The DyanmicMock object also has a MockInstance method that returns an instance of the Interface. Using this technique saves us having to create a concrete Mock command. Here's the resulting code:
[TestFixture]
public class CommandExecutorTests
{
[Test]
public void ExecuteMultipleCommands()
{
// Setup our mock Commands
DynamicMock cmd1 = new DynamicMock(typeof (ICommand));
DynamicMock cmd2 = new DynamicMock(typeof (ICommand));
// Set our expectation that the execute method will
// be called on each command
cmd1.Expect("Execute");
cmd2.Expect("Execute");
CommandExecutor executor = new CommandExecutor();
// Call our execute method on our executor
// passing in an array of mock commands, using the
// MockInstance property to create the instances.
executor.Execute( new ICommand[] {(ICommand) md1.MockInstance,
(ICommand) cmd2.MockInstance});
// Use the Verify method on the DynamicMock to
// ensure that all of our expectations have been met.
cmd1.Verify();
cmd2.Verify();
}
}
While I still have reservations about the extent to which MockObjects are useful, I think that NMock and its DynamicMocks are a useful technique to quickly produce loosely coupled test code.