I am using RhinoMocks, and I have a Mock which has a property I need to behave as a real property - updating its value when set, and also trigger PropertyChanged when the property is changed.
The interface of the mocked object is in essence this:
public interface IFoo
{
event PropertyChangedEventHandler PropertyChanged;
int Bar { get; set; }
}
When creating the mock I set PropertyBehavior - which makes it actually update its faked value:
var mocks = new MockRepository();
var fakeFoo = mocks.DynamicMock<IFoo>();
SetupResult.For(fakeFoo.Bar).PropertyBehavior();
But when I update the value PropertyChanged isn't triggered. Now, the interface doesn't implement the INotifyPropertyChanged interface as it is an interface.. How can I make PropertyChanged triggered?
The role of listener and mutator may sometimes be combined in the same class (e.g. in an adapter), but both roles should not be tested together.
In one test, you merely verify that your listening class reacts to the PropertyChanged
event as designed. You don't care about what caused the property to change in that test:
[Test]
public void Updates_Caption_when_Bar_PropertyChanged()
{
var foo = MockRepository.GenerateStub<IFoo>();
foo.Bar = "sometestvalue1";
var underTest = new UnderTest(foo);
// change property and raise PropertyChanged event on mock object
foo.Bar = "sometestvalue2";
foo.Raise(x=>x.PropertyChanged+=null,
foo,
new PropertyChangedEventArgs("Bar"));
// assert that the class under test reacted as designed
Assert.AreEqual("sometestvalue2", underTest.Caption);
// or if the the expected state change is hard to verify,
// you might just verify that the property was at least read
foo.AssertWasCalled(x => { var y = foo.Bar; } );
}
In another test, you verify that your class plays its mutator role as designed:
[Test]
public void Reset_clears_Foo_Bar()
{
var foo = MockRepository.GenerateStub<IFoo>();
foo.Bar = "some string which is not null";
var underTest = new UnderTest(foo);
underTest.Reset();
// assert that the class under test updated the Bar property as designed
Assert.IsNull(foo.Bar);
}
This way, it is never necessary to put real logic into your mock objects like you are trying to do. This does require that you design your classes for testability; it is hard to add such tests to existing classes. Hence the practice of test driven development.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With