Reputation: 2583
I'm having some issues trying to use RhinoMocks to figure out if calling a method in my class under test, a certain number of other methods is being called too. My class to be tested:
public class OrderMessageHandler : IHandleMessages<UpdateOrder>
{
public virtual IRepository Repository { get; set; }
public void Handle(UpdateOrder message)
{
if (!message.Order.Confirmed) return;
using (var om = new OperationManager())
{
try
{
om.BeginOperation();
LVR.Order.Model.OrderHeader order = ConvertToLocalOrderHeader(message.Order);
Repository.SaveUpdate(order);
om.CommitOperation();
}
catch (Exception ex)
{
om.RollbackOperation();
// other stuff here
}
}
}
internal virtual LVR.Order.Model.OrderHeader ConvertToLocalOrderHeader(Protocol.DTO.OrderHeader order)
{
// do stuff here, and call Repository.GetAll<Country>()
}
}
Here's my test method
[Fact]
public void ConvertToLocalOrderHeader_GivenConfirmedOrderMessage_CallTheConversionMethods()
{
// create a partial mock 'cause I want some of the implementation to be the true sut class
var sut = MockRepository.GeneratePartialMock<OrderMessageHandler>();
// create a stub for the repository, in order to avoid hitting the db
sut.Repository = MockRepository.GenerateStub<IRepository>();
sut.Repository.Stub(r => r.GetAll<Country>())
.Return(
new List<Country>
{
new Country {CountryID = "IT", Description = "Italy"},
new Country {CountryID = "US", Description = "United States"}
}.AsQueryable()
);
sut.Repository.Stub(r => r.SaveUpdate<OrderHeader>(Arg<OrderHeader>.Is.Anything));
// call the method I want to test
sut.Handle(new UpdateOrder
{
Order = order,
EventId = new Guid(),
EventTime = DateTime.Now
});
// verify that the method has been called (this is useless in my real test, I put it here just to understand why it doesn't work)
sut.AssertWasCalled(s => s.Handle(Arg<UpdateOrder>.Is.Anything));
// verify that an inner method (virtual) has been called during the execution of sut.handle()
sut.AssertWasCalled(s => s.ConvertToLocalOrderHeader(order));
}
In the 2 sut.AssertWasCalled
calls, I receive an error Object reference not set to an instance of an object. . The reason is that sut.AssertWasCalled
make a call to the method i'm verifying... thus
sut.AssertWasCalled(s => s.Handle(Arg<UpdateOrder>.Is.Anything));
calls
sut.Handle(null)
And being null the parameter the method throws an exception. Too bad the problem is that it shouldn't re-call the method but just tell me if it has never benn called before in the test method. What's wrong here?
Edit:
as per suggestion received in the comments, I tried a different approach (given that I don't like the expect/verify flavour). Here's the test method:
[Fact]
public void ConvertToLocalOrderHeader_GivenConfirmedOrderMessage_CallTheConversionMethods2()
{
var mocks = new MockRepository();
var sut = mocks.PartialMock<OrderMessageHandler>();
sut.Repository = mocks.Stub<IRepository>();
sut.Repository.Stub(r => r.GetAll<Country>())
.Return(
new List<Country>
{
new Country {CountryID = "IT", Description = "Italy"},
new Country {CountryID = "US", Description = "United States"}
}.AsQueryable()
);
sut.Repository.Stub(r => r.SaveUpdate<OrderHeader>(Arg<OrderHeader>.Is.Anything));
Expect.Call(() => sut.Handle(Arg<UpdateOrder>.Is.Anything));
sut.Replay();
sut.Handle(new UpdateOrder
{
Order = order,
EventId = new Guid(),
EventTime = DateTime.Now
});
mocks.VerifyAll();
}
Adn here's the error I had:
System.InvalidOperationException
Previous method 'OrderMessageHandler.get_Repository();' requires a return value or an exception to throw.
The error is thrown by the line of code
Expect.Call(() => sut.Handle(Arg<UpdateOrder>.Is.Anything));
So, no luck even with this approach...
Any other idea?
Upvotes: 1
Views: 737
Reputation: 2583
I found out what the problem was: the method ConvertToLocalOrderHeader
should be declared at least protected internal
in order to let Rhinomocks override it. Virtual
is not enough, being the testing class a differente class.
Very easy solution for a problem that took me hours to be solved :/
Upvotes: 3