A co-worker presented me with a scenario where assigning and accessing a property from a Rhino Mocks stub worked as expected, but changing the stub to a dynamic mock caused the test to fail. This didn’t really seem like a stub-versus-mock question since stubs and dynamic mocks generally function similarly, with the difference being that mocks allow you to verify expectations whereas stubs only allow you to stub return values.
Here’s a simplified version of the problem:
[TestMethod] public void TestWithStub() { var sampleStub = MockRepository.GenerateStub<ISample>(); sampleStub.Value = "bar"; // success! Assert.AreEqual("bar", sampleStub.Value); } [TestMethod] public void TestWithMock() { var sampleMock = MockRepository.GenerateMock<ISample>(); sampleMock.Value = "foo"; // fail! Assert.AreEqual("foo", sampleMock.Value); }
I’ve seen guidance online that suggests this is the correct way to handle stubbed properties. This is primarily what makes the issue confusing to me. However, per the Rhino Mocks 3.3 Quick Reference Guide, the correct way to handle property getters and setters for mocks is to use Expect.Call(foo.Name).Return(“Bob”) and Expect.Call(foo.Name = “Bob”), respectively. The quick reference guide also identifies a way to do “automatic properties” by using the PropertyBehavior method. The PropertyBehavior method allows properties in mocks to function like they do in stubs. The behavior is enabled on stubs be default, which is what causes the out-of-the-box behaviors to be different.
By adding a call to PropertyBehavior, the seemingly-correct sample test above succeeds.
[TestMethod] public void TestWithMock() { var sampleMock = MockRepository.GenerateMock<ISample>(); sampleMock.Expect(x => x.Value).PropertyBehavior(); sampleMock.Value = "foo"; // success! Assert.AreEqual("foo", sampleMock.Value); }
Note that although we use an Expect method, there is no expectation set when using the PropertyBehavior method. This means that the test will pass even if the property is not used at all. If you need to verify getters and setters, you should use mock.Expect(x => x.Value).Return(“foo”) and mock.Expect(x => x.Value = “bar”).
I’m studying at University of Pennsylvania and I wish to voice my affection for your kindheartedness toward students who seek help with this one topic. You have put in an significant level of dedication into these solutions, and it has permitted scholars in our field to acquire great benefits. Do know that this work means a lot to all of us.