Using NMock and DynamicMocks in Test Driven Development

I was pairing with someone last night trying to test the Command pattern which lead to a useful example of using NMock to create a dynamic Mock object to help test it.  Here are some notes on how NMock can be used to create DynamicMock objects based on an interface to quickly create loosely-coupled test code.

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.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值