views:

2476

answers:

5

I have a mocked object that is passed as a constructor argument to another object.

How can I test that a mocked object's property has been called? This is code I am using currently:

INewContactAttributes newContact = MockRepository.GenerateMock<INewContactAttributes>();
newContact.Stub(x => x.Forenames).Return("One Two Three");
someobject.ConsumeContact(newContact);
newContact.AssertWasCalled(x => { var dummy = x.Forenames; });

This works except when within the "someobject" the getter on Forenames property is used multiple times. That's when I get "Rhino.Mocks.Exceptions.ExpectationViolationException: INewContactAttributes.get_Forenames(); Expected #1, Actual #2.."

Simply using

newContact.AssertWasCalled(x => { var dummy = x.Forenames; }, options => options.Repeat.Any());

does not work and gives the error below:

"The expectation was removed from the waiting expectations list, did you call Repeat.Any() ? This is not supported in AssertWasCalled()."

So how do I cater for the multiple calls?

+2  A: 

What is your motivation behind checking the number of times it is called? Is it a particularly expensive operation? If so, then I would suggest that you put it behind a method instead as, semantically speaking, properties should be inexpensive calls.

Also, checking the number of times a property is called is not the thrust of unit testing (don't worry it's a common mistake to test too much, we've all been there). What you should really be testing is that given the state of your mock object that the method produces the expected output. The number of times a method is called to do that doesn't really matter (unless it's a service to send an email or something). It is an implementation detail which you normally wouldn't test as a simple refactor would break your tests as they would be too specific.

Garry Shutler
Thanks Garry. I actually don't want to test how many times the getter was called, merely that it was called. As it happens the "someobject" uses it internally twice. That's the cause of the problem; there appears to be no way to use .Repeat.Any() with the AssertWasCalled.
Confused
But generally verifying that the output is correct verifies that the property was called. How could the output be correct if the property was not called?
Garry Shutler
Garry, your comments are valid, but you also have to say that there are basically two schools of mock testing: state-based and interaction-based. Asserting how many times a method is called is perfectly valid in interaction-based testing. And sometimes the state doesn't change.
Igor Brejc
A: 

Hi, What about

newContact.Expect( c => c.ForeNames ).Return( ... ).Repeat.Any()
Lennaert
+12  A: 

newContact.AssertWasCalled(x => { var dummy = x.Forenames; }, options => options.Repeat.AtLeastOnce());

Repeat.Any does not work with AssertWasCalled because 0 counts as any... so if it WASN'T called, the AsserWasCalled would return TRUE even if it wasn't called.

Thanks, this saved me time. Should be the best answer to the question (IMO)
Thies
A: 

Depending on your version of Rhino you are using, you can use:

// Call to mock object here
LastCall.IgnoreArguments().Repeat.Never();
vanslly
+2  A: 

I agree with chris answer

newContact.AssertWasCalled(x => { var dummy = x.Forenames; }, options => options.Repeat.AtLeastOnce());

Additionally If you know exactly how many times the property would be called you can do

newContact.AssertWasCalled(x => { var dummy = x.Forenames; }, options => options.Repeat.Times(n));

where n is an int.

Usman