Monday, June 16, 2014

Rhino Mocks Basics

Rhino mocks is a mocking framework for the .Net platform which eases the process of creating mock objects for the purposes of unit testing and test driven development.


Creating mock objects

in the following example our aim is to test the ItemController, but the ItemController has a dependency on the ItemRepository. we need to inject this dependency into the constructor of the ItemController in order to be able to instantiate it and test it.


the first concern with the above scenario is that the item repository probably accesses a database which will make our tests run very slowly.

the second concern is that we only want to test the behavior of the item controller classes and using the above method we are actually testing the behavior of the ItemRepository class too. the dependency on ItemRepository also complicates debugging because the scope of the tests is widened to include both of the classes, if something was to go wrong we would have to look into both these classes to find the source of that problem.

Rhino mocks allows us to create a mock object of ItemRepository if we can provide it with the appropriate interface. Rhino mocks internally uses a third party library Castle Dynamic Proxy to create proxy classes from interfaces.


Now that we have created our mock object the arrange portion of our test is complete.
we can now begin the act portion of our test. we would like to test the behavior inside the ItemController index method.

We can write the act portion of our method by calling the Index method of the ItemController and then using Rhino mocks extension method AssertWasCalled, we can verify that the method GetAllItems of the ItemRepository was called by the Index method of the ItemController.


Creating Stubs

Stubs are controllable replacements for dependencies. by creating stubs you can control the program flow and avoid dealing with a dependency directly.

in the following scenario, our method uses the ItemValidator to validate the item being passed in. if the item is valid then it is passed to the ItemRepository to be saved, but if its not then an argument exception is thrown.
our method above depends on the ItemValidator and if we were to create item instances(valid and invalid items) just so we could write some unit tests for the above method, then we would essentially be testing both the above method and the ItemValidator class which means that our test is not isolated.

the other option is to mock the ItemValidator however  the ItemValidator class might be too complex to be mocked and we would not want to be held back from writing production code, having to create hand rolled mocks every time we encounter such dependencies.


Fortunately an stub can be created using Rhino mocks to overcome the above problem. 
an stub is essentially a mocked object that we can setup to return an expected value.  in the below code the mockItemValidator and mockItemRepository dependencies are injected into the ItemController Constructor.

since the itemValidator is a mock then it does not have any implementation, therefor we have to configure it so that it does what we want it to do.
by default an stub returns the default values of it's methods. the ItemValidator's Validate method returns a boolean and the default value of a boolean is false. however we would like to write a test to confirm that the Save method calls the save method of the ItemRepository and that would require the Validate method to return true. the below snippet basically states, create a stub from mockItemValidator and configures it so that if the validate method is called and passed in any Item then it should return a true boolean.

The completed test case below demonstrates how we could use stubs to control program flow and get rid of dependencies. we set up our stub to return a true value and therefor direct the flow to the ItemRepository save method. if we were to change the stub to return false or if we didn't include the stub so that it would return the default value of false, then we would be able to direct the flow to the else statement and test that the ArgumentException is thrown.

Constraints

Constraints enable you to verify that the arguments passed into a method match a certain criteria.
Imagine that the responsibility of creating an Item in the above scenario was given to the ItemController and that we had to pass in the primitive types that comprise an item into the save method instead of an actual instance of an item as shown in the below code.

Now to test the above scenario we have to pass in the parameters, but in the assert section we encounter a problem. the ItemController save method takes in the primitives and creates an instance of Item and then passed that Item to the ItemRepository to be saved.

Because the assert section checks for reference equality we cant create an instance of an item with the same primitive values and use it in the assert section, this would cause the test to fail since object references point to two different instances of Item.

Rhino Mocks provides the Is, Matches, List, Text constraints for such scenarios.

In this scenario we can use the matches constraint to check that each primitive matches the property value of the item being saved by the ItemRepository.


No comments :

Post a Comment