A collection of learnings and opinions.

Showing posts with label moq. Show all posts
Showing posts with label moq. Show all posts

Monday, October 5, 2009

Simpler reference equality on mocks

When mocking with MoQ I find myself regularly setting up the .Equals() method on the mocks. It just makes for more readable code to be able to ask a collection whether it .Contains() the mock than writing out the iteration myself.

But it does bloat my test-cases somewhat. Here's an example setting up a mock of a class with the equality set that returns true if it's compared to itself:
[Test(Description = "Mock of equals on an instance succeeds")]
public void MockingEquals_SameInstance_AreEqual() {
 var mocker = new Mock<SomeClass>();
 mocker.Setup(x => x.Equals(mocker.Object)).Returns(true);

 var mockedObject = mocker.Object;

 Assert.That(mockedObject.Equals(mockedObject));
}

That's fine if it's only in one test, but I don't like to repeat that all over my code. My first thought was to make a convenience method which set up the equality for me:
public static Mock<T> ReferenceEquals<T>(Mock<T> mock) where T : class {
 mock.Setup(m => m.Equals(mock.Object)).Returns(true);
 return mock;
}

Sticking this in some public place now allows me to set up my test from before like this:

[Test(Description = "Mock of equals on an instance succeeds")]
public void MockingEquals_SameInstance_AreEqual() {
 var mocker = new Mock<SomeClass>();
 ReferenceEquals(mocker);

 var mockedObject = mocker.Object;

 Assert.That(mockedObject.Equals(mockedObject));
}

That's certainly better. But, we can do better than that, can't we? Let's make it an extension-method, for great success! To use this code the class containing the extension-method must be static.

public static void HasReferenceEquality<T>(this Mock<T> mock) where T : class {
 mock.Setup(m => m.Equals(mock.Object)).Returns(true);
}

And with that our test has been transferred to the (in my opinion) much more readable:
[Test(Description = "Mock of equals on an instance succeeds")]
public void MockingEquals_SameInstance_AreEqual() {
 var mocker = new Mock<SomeClass>();
 mocker.HasReferenceEquality();

 var mockedObject = mocker.Object;

 Assert.That(mockedObject.Equals(mockedObject));
}

Great success!

Friday, September 25, 2009

MoQ with Collections, or equality woes

Still working with the fine mocking-framework MoQ, I came across a somewhat surprising facet (and I don't like surprises).
I'm mocking out a class which should be added to a collection after a method-call, like so:

public class SomeClass{

}

public class Container {
private List<SomeClass>; classes = new List<SomeClass>();

public IEnumerable<SomeClass> Classes {
get {
return classes;
}
}

public void addSomeClass(SomeClass instance) {
classes.Add(instance);
}
}

[Test]
public void ContainerContainsAddedClassAfterAdd() {
var mockSomeClass = new Mock<SomeClass>();
mockSomeClass.Setup(c => c.Equals(mockSomeClass.Object)).Return(true);

var Container = new Container();
Container.addSomeClass(mockSomeClass.Object);

Assert(Container.Classes.Contains(mockSomeClass.Object));
}

This works well, the mock is added to the Container's collection and the setup of the Equals method on the mock makes sure the IEnumerable.Contains() return true.
However there's always some complication. The class I'm really mocking out is not as simple as our SomeClass. It's something like this:

public class SomeClassOverridingEquals{
public virtual Equals(SomeClassOverridingEquals other) {
return false;
}

public override Equals(object obj) {
var other = obj as SomeClassOverridingEquals;

if (other != null) return Equals(other); // calls the override
return false;
}
}

[Test]
public void ContainerContainsAddedClassOverridingEqualsAfterAdd() {
var mockSomeClass = new Mock<SomeClassOverridingEquals>();
mockSomeClass.Setup(c => c.Equals(mockSomeClass.Object)).Return(true);

var Container = new Container();
Container.addSomeClass(mockSomeClass.Object);

Assert(Container.Classes.Contains(mockSomeClass.Object)); // fails
}

The class contains an override for the Equals method for its own specific type, and the Setup method for the mock does not seem to be able to mock out that specific method (only overriding the more general Equals(object)). Thus the test fails.

I have so far found no way of working around this quite common pattern, other than rewriting the class not to use the overriding equals.

I don't like that.

Anyone have any ideas?

Thursday, September 24, 2009

Mocking expectations on Property setters with MoQ

When mocking out your classes using the fabulous MoQ mocking-framework you may sometimes need to mock out an expectation that a property on your mocked object should be set.

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!