It took me some time to figure out how to do this. The documentation on the MoQ quickstart wiki says to use the following pattern:
// expects an invocation to set the value to "foo"
mock.SetupSet(foo => foo.Name = "foo");
Well, I tried this with an object:
public class SomeClass {
public string Something { get; set; }
}
[Test]
public void PropertySetupOnMock() {
const string someString = "Should be set";
var mocker = new Mock<SomeClass>();
mocker.SetupSet(x => x.Something = someString); //exception here
mocker.Object.Something = someString;
mocker.VerifySet(x => x.Something);
}
This only gave me an error on the line with the
SetupSet:System.ArgumentException: Invalid expectation on a non-overridable member.
Well, that's strange. After some looking around it turns out that MoQ does its magic by extending the class that's being mocked. It cannot extend non-virtual properties, so this
Something property cannot be extended and thus cannot be Setup.What can be done about this? The easiest immediate solution would be to mark the property
virtual, like so:
public class SomeClass {
public virtual string Something { get; set; }
}
But do we really want to decorate every property on the objects as virtual? Not really. A better solution is to push the property up to an interface and mock that interface instead, like so:
public interface IWithProperty {
public string Something { get; set; }
}
public class SomeClass : IWithProperty {
public string Something { get; set; }
}
[Test]
public void PropertySetupOnInterfaceMock() {
const string someString = "Should be set";
var mocker = new Mock<IWithProperty>();
mocker.SetupSet(x => x.Something = someString); //no exception here
mocker.Object.Something = someString;
mocker.VerifySet(x => x.Something);
}
Thus allowing me to mock it out and test that the property setter was indeed called. Yay!
If anyone has any better ways of doing this I'd love to hear from you!
