|
||||||||||||||||||
|
||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Note: This is an unedited contribution. If this article is inappropriate,
needs attention or copies someone else's work without reference then please
Report This Article
IntroductionSince the 3rd of October 2008, Ayende has released a new version of Rhino Mocks. Rhino Mocks is "A dynamic mock object framework for the .Net platform. It's purpose is to ease testing by allowing the developer to create mock implementations of custom objects and verify the interactions using unit testing." This version now supports the AAA (Arrange, Act and Assert) syntax. The major feature in Rhino Mocks 3.5 is the AAA syntax. Arrange, Act, Assert is a classic way to setup your tests. First you arrange the state, then you execute the code under test, finally you assert that the expected state change happened. Which makes it more easy to read and use. I will try to explain how to use it and show the difference between the old and the new syntax using VB.Net. This article is not about why and when you should use Mocks. This is also not an article on best practices. The Repository for example is kept light it is just there to explain things. I will also write just on test to see if the service returns the correct something if it gets called. For this it needs to use the Repository implementation but because we don't want the test to go to the database I will Mock it out. You can find me and some other bright people at LessThanDot Prerequisites
Set upFor this example I will use A Service and a Repository. The Service calls the Repository to do the dirty work. Both also have an interface which is usually the easier way to Mock something. First we create the IService and IRepository interfaces Namespace Service
Public Interface IService
Function FindAllProducts() As IList(Of Model.Product)
End Interface
End Namespace
Namespace Repository
Public Interface IRepository(Of T)
Function FindAll() As IList(Of T)
End Interface
End Namespace
Now both Interfaces need an implementation. Nothing fancy, just a simple implementation. The Repository code is there just as an example. It won't even work. And it doesn't need to work because we are going to mock it out. First the service. This simply calls the repository. It also takes a IRepository(Of Model.Product) as a parameter so that we can inject an implementation in it. Namespace Service
Public Class Service
Implements IService
Private _Repository As Repository.IRepository(Of Model.Product)
Public Sub New(ByVal Repository As Repository.IRepository(Of Model.Product))
_Repository = Repository
End Sub
Public Function FindAllProducts() As IList(Of Model.Product) _
Implements IService.FindAllProducts
Return _Repository.FindAll
End Function
End Class
End Namespace
And now an implementation of IRepository which we won't use in the tests. Imports System.Data.SqlClient
Namespace Repository
Public Class ProductRepository
Implements IRepository(Of Model.Product)
'''
The testsRhino Mocks 3.4In the previous version of Rhino Mocks you used Replay and Verify syntax. So our test would look like this. Imports NUnit.Framework
Imports Rhino.Mocks
Namespace MockedTest34
You see here that we an Instance of MockRepository. That MockRepository will make us a Mock using the DynamicMock method. In this case we Mock the Repository. We then make our Service and we pass in our Mocked Repository. After that we set our Expectation. We expect that the Findall method will be called on the Repository. We now have to call The ReplayAll method on the MockRepository object. Lastly we assert if the service returns something, we don't really care what that may be but since our function must return an Ilist(Of Model.Product) we don't really have to check that. Rhino Mocks 3.5In the new version the old code still works ;-). But we can (and should) use the newer AAA syntax instead. As you will see in the code example it is a bit simpler to use. Imports Nunit.FrameWork
Imports Rhino.Mocks
Namespace MockedTest35
'''
First we see that we no longer have to make and instance of MockRepository. We will use the Static/Shared methods of MockRepository instead. To make the mock we use the GenerateMock method of the MockRepository. Then we pass that mocked object to a new Service. We set our expectations via an extension method called stub. it uses a lambda expression to decide which method will be called. We set the desired return value and we use IgnoreArguments although not really needed in this instance because findall has no arguments. After that we call the service method and see if it returns something. As you can see the new method no longer needs the ReplayAll and VerifyAll syntax either. I hope this explains the difference well enough for you to go out and use this wonderfull product. Points of InterestIf you switch from Rhino Mocks 3.4 to Rhino Mocks 3.5 the compiler will complain that Expect has no such method on the lines where you have Expect.Call. This is easily solved by adding Rhino.Mocks. In front of it. this is caused by the fact that Ayende also added an Extension method with the same name and the compiler can't make the difference. Adding an imports doesn't help. History10/07/2008 First version 10/07/2008 Added a link to an AAA explanation article. And corrected some typos.
|
|||||||||||||||||