1. Rhino Mock Implemetation Process
For Implementing the Mocking, I used Rhino.Mocks Namespace of version No 3.6.0.0 during unit testing
in my project.
Before starting we just need to know basic knowledge about Rhino Mocks,i.e
what is Rhino Mocks
what is a AAA..
what is difference b/w Mock and Stub.
Rhino Mocks
A dynamic mock object framework for the .Net platform. Its purpose is to ease testing by
allowing the developer to create mock implementations of custom objects and verify the
interactions using unit testing.
Rhino Mocks allows you to easily create mock objects and setup a wide range of expectations on
them using strongly typed notation instead of compiler-opaque strings.
AAA Syntax - Arrange, Act, Assert
This is where Rhino Mocks 3.5 is really interesting - for me at least. We can now express our
mock object is a much cleaner fashion, taking advantage of .Net 3.5 extension methods and
lambda questions. Below, is the example of using the Mock object.
[Test]
public void GenerateMock_TakePaymentViaPaymentProcessorUsingMockService()
{
IPaymentProcessing mockProxy = MockRepository.GenerateMock<IPaymentProcessing>(); #1
mockProxy.Expect(x => x.TakePayment(1, 1, 10.0)) #2
.Constraints(Is.Equal(1), Is.Equal(1), Is.Equal(10.0))
.Return(true);
PaymentProcessor pp = new PaymentProcessor(mockProxy);
bool result = pp.TakePayment(1, 1, 10.0);
Assert.IsTrue(result);
2. mockProxy.VerifyAllExpectations (); #3
}
#1 Here we tell Rhino Mocks to create us a mock object of type IPaymentProcessing.
#2 Next we define our mock. Here, we are saying we expect TakePayment to be called, we then
add some constraints about what the parameters passed in much be, finally defining that true
be returned when this is called.
#3 Finally, we verify the exceptions we set in #2 where correct.
I find this new approach to be much easier to read, explain and write. The first time I tried this, I
actually mistaken Constraints for Return and as such the following exception was thrown.
mockProxy.Expect(x => x.TakePayment(1, 1, 10.0)).Constraints(Is.Equal(true)); = failed:
System.InvalidOperationException : The number of constraints is not the same as the number of
the method's parameters!
Just be aware of these new constraints on the parameters.
But, not only can we use this for creating mocks, but we can also create Stubs.
[Test]
public void GenerateStub_TakePaymentViaPaymentProcessorUsingMockService()
{
IPaymentProcessing stubProxy = MockRepository.GenerateStub<IPaymentProcessing>(); #1
stubProxy.Stub(action => action.TakePayment(1, 1, 10.0)).Return(true); #2
PaymentProcessor pp = new PaymentProcessor(stubProxy);
bool result = pp.TakePayment(1, 1, 10.0);
Assert.IsTrue(result);
}
#1 Generate the stub
#2 Define the stub
How cool is that!! Two lines of code to create our stub!
[Test]
public void
GenerateStub_AssertWasCalled_TakePaymentViaPaymentProcessorUsingMockService()
{
IPaymentProcessing stubProxy = MockRepository.GenerateStub<IPaymentProcessing>();
stubProxy.Stub(action => action.TakePayment(1, 1, 10.0)).Return(true);
3. PaymentProcessor pp = new PaymentProcessor(stubProxy);
bool result = pp.TakePayment(1, 1, 10.0);
Assert.IsTrue(result);
stubProxy.AssertWasCalled(x => x.TakePayment(1, 1, 10.00)); #1
}
#1 With stubs, we can also verify that the method was called. Notice this AssertWasCalled is an
extension method Rhino Mocks has added to the interface. gain, this is helping with the
readability and demonstrates an excellent use of Extension Methods.
If AssertWasCalled failed, then the following exception would be thrown and the test would
fail.
Expected that IPaymentProcessing.TakePayment(1, 1, 10); would be called, but it was not found
on the actual calls made on the mocked object.
The difference between stubs and mocks
I want to focus on the difference from the point of view of Rhino Mocks.
A mock is an object that we can set expectations on, and which will verify that the expected actions
have indeed occurred. A stub is an object that you use in order to pass to the code under test. You can
setup expectations on it, so it would act in certain ways, but those expectations will never be verified. A
stub's properties will automatically behave like normal properties, and you can't set expectations on
them.
If you want to verify the behavior of the code under test, you will use a mock with the appropriate
expectation, and verify that. If you want just to pass a value that may need to act in a certain way, but
isn't the focus of this test, you will use a stub.
IMPORTANT: A stub will never cause a test to fail.
No Expects then no need to call VerifyAllExpectations() .
We also Crearte for GenerateMock in any abstract class ,for example
namespace Corp.Database
{
public abstract class DatabaseCommand : IDisposable
{ protected DatabaseCommand(string query);
protected DatabaseCommand(string query, string[] parameterNames,
params object[] parameters);
}
4. }
// In the Test cs contains
namespace
Tests.CustomerCare.Infrastructure.Refund.RefundRequestRepositoryTests
{ public partial class RefundRequestRepositoryTests
{
private DatabaseCommand CreateDeleteCommand(long ticketId)
{
DatabaseCommand command =
MockRepository.GenerateMock<DatabaseCommand>("storedProcName");
_commandFactory.Expect(cf =>
cf.CreateDeleteCommand(ticketId)).Return(command);
return command;
}
}
}
Then after that
We can take Tests.CustomerCare project . In that project take one class
CallDetailsPresenterTests.cs
namespace Tests.CustomerCare
{
[TestFixture]
public class CallDetailsPresenterTests
{
private CallDetailsPresenter _presenter;
private ITicketRepository _ticketRepository;
}
[SetUp]
public void Setup()
{
private CallDetailsPresenter _presenter;
_ticketRepository =
MockRepository.GenerateMock<ITicketRepository>();//Generate Mock and
Generate Stub can only be created for interfaces. #1
5. _presenter = new CallDetailsPresenter(navigateCommandFactory,…);
//Initilizing the class object ..
}
[TearDown]
public void TearDown()
{
_ticketRepository.VerifyAllExpectations();#3
//It verifies all exceptions
}
[Test]
public void CanUpdateCall()
{
_ticketRepository.Expect(tr =>
tr.Populate(_ticketId,_ticketHistoryRepository,_ticketAttachmentRepository,
_ticketDiscRepository,_transactionRepository,
_refundRequestRepository)).Return(_fakeTicket);// Expect method was placed in
in any presnter .. #2
Then after that call the particular presenter.
_presenter.Save(sendEmail);
// after invoking the method in the presenter all the Expect methods are
invoked and verifications of this expections are done in teardown.
}
Implementation is developed in the TicketRepository class file,
Method name is
public ITicket Populate(long ticketId, ITicketHistoryRepository
historyRepository, ITicketAttachmentRepository attachmentRepository,
ITicketDiscRepository discRepository, ITransactionRepository
transactionRepository, IRefundRequestRepository refundRequestRepository)
{Return ticket;}
But Method was called into CallDetailsPresenter