Mock.Of() and Mock.Get() in Moq
Today, I’d like to highlight a couple of features of Moq that I didn’t know about until relatively recently (thanks to a recent google+ hangout with Moq author, Daniel Cazzulino). Since learning about these features, I’ve been getting a lot of mileage out of them. But, in order to explain these two features and the different paradigm they represent, let me reference my normal use of Moq.
Let’s say we have some class PencilSharpener that takes an IPencil and sharpens it, and we want to verify that this is accomplished by setting the Pencil’s length and sharpness properties:
public void Sharpen_Sets_IsSharp_To_True() { var myPencilDouble = new Mock(); myPencilDouble.SetupProperty(pencil => pencil.IsSharp); myPencilDouble.Object.IsSharp = false; myPencilDouble.SetupProperty(pencil => pencil.Length); myPencilDouble.Object.Length = 12; var mySharpener = new PencilSharpener(); mySharpener.Sharpen(myPencilDouble.Object); Assert.IsTrue(myPencilDouble.Object.IsSharp); }
So, I create a test double for the pencil, and I do some setup on it, and then I pass it into my sharpener, after which I verify that the sharpener mutates it in an expected way. Fairly straight forward. I create the double and then I manipulate its setup, before passing its object in to my class under test. (Incidentally, I realize that I could call “SetupAllProperties()”, but I’m not doing that for illustrative purposes).
But, sometimes I’d rather not think of the test double as a double, but just some object that I’m passing in. That is, perhaps I don’t need to invoke any setup on it, and I just want to reason about the actual proxy implementation, rather than stub.object. Well, that’s where Mock.Of<>() comes in:
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")] public void Sharpen_Sets_IsSharp_To_True() { var myPencil = Mock.Of(); myPencil.IsSharp = false; var mySharpener = new PencilSharpener(); mySharpener.Sharpen(myPencil); Assert.IsTrue(myPencil.IsSharp); }
Much cleaner, eh? I never knew I could do this, and I love it. In many tests now, I can reason about the object not as a Mock, but as a T, which is an enormous boost to readability when extensive setup is not required.
Ah, but Erik, what if you get buyer’s remorse? What if you have some test that starts off simple and then over time and some production cycles, you find that you need to verify it, or do some setup. What if we have the test above, but the Sharpen() method of PencilSharpener suddenly makes a call to a new CanBeSharpened() method on IPencil that must suddenly return true… do we need to scrap this approach and go back to the old way? Well, no, as it turns out:
[TestMethod, Owner("ebd"), TestCategory("Proven"), TestCategory("Unit")] public void Sharpen_Sets_IsSharp_To_True() { var myPencil = Mock.Of(); myPencil.IsSharp = false; Mock.Get(myPencil).Setup(pencil => pencil.CanBeSharpened()).Returns(true); var mySharpener = new PencilSharpener(); mySharpener.Sharpen(myPencil); Assert.IsTrue(myPencil.IsSharp); }
Notice the third line in this test. Mock.Get() takes some T and grabs the Mock containing it for you, if applicable (you’ll get runtime exceptions if you try this on something that isn’t a Mock’s object). So, if you want to stay in the context of creating a T, but you need to “cheat”, this gives you that ability.
The reason I find this so helpful is that I tend to pick one of these modes of thinking and stick with it for the duration of the test. If I’m creating a true mock with the framework — an elaborate test double with lots of customized returns and callbacks and events — I prefer to instantiate a new Mock(). If, on the other hand, the test double is relatively lightweight, I prefer to think of it simply as a T, even if I do need to “cheat” and make the odd setup or verify call on it. I find that this distinction aids a lot in readability, and I’m taking full advantage. I realize that one could simply retain a reference to the Mock and another to the T, but I’m not really much of a fan (though I’m sure I do it now and again). The problem with that, as I see it, is that you’re maintaining two levels of abstraction simultaneously, which is awkward and tends to be confusing for maintainers (or you, later).
Anyway, I hope that some of you will find this as useful as I did.
By the way, if you liked this post and you're new here, check out this page as a good place to start for more content that you might enjoy.
Exactly what I wanted to know. Thanks for this complete and eloquent discussion!
I’m glad it helped, and my pleasure!
GREAT_POST, very helpful for jumping in. Just wanted to add something to help others (and maybe you too). Not sure if this is a newer feature from you post but if you are setting up method calls or prop calls they can be done at the time you create the Mock. var myPencil = Mock.Of(p=> p.CanBeSharpened() && p.IsSharp == false); note that you do not need to say CanBeSharpened == true it becomes implied. have not tried !p.IsSharp instead of p.IsSharp == true but i think that would work too. You can chain as many prop and method calls you… Read more »
Truth be told, it’s been a while since I’ve used Moq, so that might indeed be a new feature. Either way, it’s new info to me. Thanks for the tip!
sure thing, this post shows fairly high on the list when you search for Mock.Of so wanted to share the knowledge. What are you using instead of moq?
I switched a while back to using Telerik’s JustMock. At the time, I liked the semantics a little better, and I don’t think Moq was especially active in being maintained (which may have changed since).