Monday, September 05, 2011

Moles with Mocking capability

Myself and a colleague of mine made a discovery when we started to do some unit test coding with moles that it doesn't have any expectation-functionality like Rhino mocks where you can specify what the incoming parameter values should be for a mocked-class.

That's when I did some searching on the web for mocking frameworks which might complement the Moles tool-set. I came across this library: http://simpledotnet.codeplex.com

It's not the best out there but it does feature one thing that other mocking frameworks (and correct me if I'm wrong) doesn't have and that is delegate mocking. I told my colleague about it and he tried it out... and it worked! It makes coding less and improves readability.

Now suppose you have a class ClassX that you want to mock.
Now with Moles you can only stub the target type by substituting the behavior with delegates.
With Simple.Net, you first create the expectation scope:

var expectationScope = new ExpectationScope();

Then you can create the mock-delegate:

var getNameMock = Mock.Delegate<MolesDelegates.Func<ClassX, string>>();

Now we stub the target class with the mock:

MClassX.AllInstances.GetName = getNameMock;

Now you set some expectations:

Expect.Exaclty(1).MethodCall(() => getNameMock(Any<ClassX>.Value)).Returns("Fred");

Run your system under test code:

ClassX x = new ClassX();
Assert.AreEqual("Fred",x.GetName());


Verify expectations are met:

AssertExpectations.IsMetFor(expectationScope); 

And now your test should succeed. Please check out the Simple.NET website to see how this mocking framework works.

Hope this helped someone.

1 comment:

Mikael Waltersson said...

If you only use one mocked object in your test and are not using ordered expectations there is no need to create a ExpectationScope instance. All mock objects have a implicitly created ExpectationScope if none is passed into the Mock.Delegate/Interface-method.

In your code sample you should get rid of the 'var expectationScope = new ExpectationScope();' line and change 'AssertExpectations.IsMetFor(expectationScope);' to 'AssertExpectations.IsMetFor(getNameMock);'