4
votes

Forgive me if this is a stupid question, but I'm fairly new at mocking, and am trying to get my head around it.

I have some unit tests (using the built-in Visual Studio 2010 Professional testing features), which use a stub that is needed by a method. I created a stub, and set the default return values for a couple of properties and a method, and all works well. I have a static class that sets up the stub, and this is used in the TestInitialize method to set up the stub...

public static AppointmentReminderProviderInterface GetMockProvider() {
  AppointmentReminderProviderInterface provider = MockRepository.GenerateStub<AppointmentReminderProviderInterface>();
  provider.Stub(p => p.ContactName).Return(MockProviderContactName);
  provider.Stub(p => p.ContactEmail).Return(MockProviderContactEmail);
  return provider;
}

Note that MockProviderContactName and MockProviderContactEmail are local string properties that contain default data for the provider. The unit tsts that check to see if things work as expeced with the default data all pass fine.

However, I now want to test what happens when one of these properties contains duff data. I thought I could just set this on the stub, but it isn't working. The test method contains the following lines...

_provider.Stub(p => p.ContactEmail).Return("invalid");
Debug.WriteLine("Provider email: <" + _provider.ContactEmail + ">");

The Debug.WriteLine() shows me that, despite the fact that I have set the ContactEmail property to return "invalid" it still returns the default email address. This causes my test to fail, as I'm expecting it to throw an exception, and it doesn't.

Anyone any idea why I can't change the return value of this property?

Thanks for any help.

2
I've never used Rhino Mocks but in other mocking frameworks I've used when you set a return value more than once, as in your case, the first value gets returned in the first method/property call, and the second value gets returned the second time you access that member (etc., etc. Also, the last value set is usually returned in further subsequent calls).Allon Guralnek
Hi Allon, thanks for the reply. If your suggestion were correct, then the Debug.WriteLine call I showed should have output the "invalid" value, and then the test method itself should have been given the original value. However, I always seem to get the default value, irrespective of what I set by calling Stub() again. Thanks anyway.Avrohom Yisroel
Redesign your tests so that you don't need to change stub return value during testing. You have to define return value only once.Alexander Stepaniuk

2 Answers

5
votes

As a tricky but working solution I'd suggest to use Do handler here. It allows to implement some logic for stubbed method/property.

See example:

var providerContactEmail = "Email1";

provider
    .Stub(p => p.ContactEmail)
    .Do((Func<string>)(() => providerContactEmail));
// here provider.ContactEmail returns "Email1"

providerContactEmail = "Email2";
// now provider.ContactEmail returns "Email2"

But in my opinion it is much better if the solution can be found which allows to don't change return value in the middle of test. :)

1
votes

Try changing

_provider.Stub(p => p.ContactEmail).Return("invalid");

To

_provider.ContactEmail = "invalid";

Assuming ContactEmail has a setter, this should work. If this doesn't resolve your issue, I'd follow Alexander Stepaniuk's advice and refactor your test so that you're not adding multiple behaviors for the same stub; I think that has something to do with your issue.