Kash Farooq's software development blog

.NET Developer

Rhino Mocks and GetArgumentsForCallsMadeOn

Posted by Kash Farooq on January 10, 2009

Rhino Mocks includes a couple of ways to ensure your dependencies are called with the correct data. One is by using Rhino Mocks Matches syntax.

Another way is by using a Rhino Mocks extension method called GetArgumentsForCallsMadeOn. I think with this method you get clearer assert error messages.

Here is some sample code to show the usage:

Let’s start with a dependency that receives some data via a parameter:

public interface IDependency {
  int DoSomething(SomeComplexType someComplexType,
                        int someInteger);
}

public class SomeComplexType {
  public string stringData { get; set;}
}

Our system under test looks like this, receiving the dependency via Dependency Injection:

public class SystemUnderTest {
  private readonly IDependency dependency;
  public SystemUnderTest(IDependency dependency) {
     this.dependency = dependency;
  }

  public int MethodUnderTest(string data1, int data2) {
	var someComplexType1 = new SomeComplexType { stringData = string.Format("Sending {0}", data1) };
	var dataReturnedByCall1 = dependency.DoSomething(someComplexType1, 1111);

	var someComplexType2 = new SomeComplexType { stringData = string.Format("Sending {0}", data2) };
	var dataReturnedByCall2 = dependency.DoSomething(someComplexType2, 2222);

	return dataReturnedByCall1 + dataReturnedByCall2;
  } 
}

To check that DoSomething is called with the correct data, we use GetArgumentsForCallsMadeOn.

[Test]
public void EnsureDependencyIsCalledWithCorrectArguments() {

	//Arrange
	var mockRepository=new MockRepository();
	var dependency = mockRepository.DynamicMock<IDependency>();
	dependency.Expect(x => x.DoSomething(null, 0))
                        .IgnoreArguments()
                        .Return(7);
	dependency.Expect(x => x.DoSomething(null, 0))
                        .IgnoreArguments()
                        .Return(3);

	//Act
	mockRepository.ReplayAll();
	var systemUnderTest=new SystemUnderTest(dependency);
	var returned = systemUnderTest.MethodUnderTest("MyData",1234);

	//Assert
	Assert.AreEqual(10,returned);

	IList<object[]> argumentsSentToDoSomething = 
             dependency.GetArgumentsForCallsMadeOn(x => x.DoSomething(null, 0));
	var arg1Call1 = (SomeComplexType)argumentsSentToDoSomething[0][0];
	var arg2Call1 = (int)argumentsSentToDoSomething[0][1];
	var arg1Call2 = (SomeComplexType)argumentsSentToDoSomething[1][0];
	var arg2Call2 = (int)argumentsSentToDoSomething[1][1];
	Assert.AreEqual("Sending MyData", arg1Call1.stringData);
	Assert.AreEqual(1111, arg2Call1);
	Assert.AreEqual("Sending 1234", arg1Call2.stringData);
	Assert.AreEqual(2222, arg2Call2);
}

GetArgumentsForCallsMadeOn is used to get arguments sent to the dependency. GetArgumentsForCallsMadeOn returns a two dimensional array of objects so you will need to cast to get to the types you are expecting. The arguments sent to the first call to DoSomething are at position 0,0 and 0,1 of this array. For the second call to DoSomething, the arguments are at position 1,0 and 1,1.

Note that the data sent in the action to GetArgumentsForCallsMadeOn can be anything (I have sent null and 0 in the example above). Your dependency has already been called at this point and we are just telling Rhino Mocks which method you want the arguments for.

A word of caution

Credit to Matt for pointing this out to me.
Be aware that GetArgumentsForCallsMadeOn is not a strongly typed way of doing things. You are getting the data sent to the dependency in a “weak” way – i.e. by grabbing data by position out of a two dimensional array. If someone changes the order of the parameters in the dependency, there is a danger that the dependent class’ test will fail, even though the code under test is correct. This would highlight that you have a test that is deeply tied to the implementation and is hindering refactoring.

About these ads

3 Responses to “Rhino Mocks and GetArgumentsForCallsMadeOn”

  1. C Surfleet said

    Really helpful, keep up the good work!

  2. Rawk said

    Thanks for this – I knew this was possible, but couldn’t find it – nice clear example :)

  3. jeroenh said

    here’s a cleaner way (IMHO): https://gist.github.com/3144300

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 )

Twitter picture

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

Facebook photo

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

Google+ photo

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

Connecting to %s

 
Follow

Get every new post delivered to your Inbox.

%d bloggers like this: