July 28, 2011

MOQ SetupSequence is great for mocking

If you use mocking frameworks, you may run into scenarios in which you want an operation to behave one way on the first call, and a different way on the second or third call. In the MOQ framework, which I use, I just discovered the SetupSequence method.

In the past, without SetupSequence, I would have to create a fake object, and design it to behave differently on each call, in accordance with my tests. That was not hard, but using SetupSequence is much more elegant. Here is a snippet from the documentation at the link below.

Rate this:

Share this:

Like this:

Related

You’ve just brought up one of my biggest issues with the standard mocking frameworks. You have to discover how they work instead of them working like everything else. Of course you have to learn how to mock something in whatever mocking framework you use. It’s the extra stuff that you have to differently than you would in your normal code. Specifically, you had to discover the SetupSequence method.

Microsoft has had a “free” (as long as you own Visual Studio Professional) mocking framework named “Moles” I’ve been using for years. It’s part of the Pex project at http://research.microsoft.com/en-us/projects/pex/. I have to test a lot of legacy code so I need a mocking framework that will let me mock any kind of method including non-virtual and static methods. TypeMock is the only other I know that will do that.

Getting back to the point, Moles allows to mock a method by simply assigning a lambda expression that does whatever you want it to do. In the code below, I am “mole-ing” the File.Exists(string) static method that is in mscorlib.dll. The Moles framework generates a class named MFile and has properties for each member you can “mole” in the File class. So below you see me setting MFile.ExistsString which is the Exists method that takes a String. I simply assign a lambda expression that returns a different value each time it is called. The point is that I don’t have to learn about SetupSequence to get this to work. Calling File.Exists() with any file name will now return true on the first call, false on the second call and throws an exception on subsequent calls.

In any case, I’m not trying to start a religious battle about which mocking framework is the best. Moles isn’t perfect by any means, but it is easy to use, free once you own Visual Studio, and allows me to do the things I need to do.

Thanks for offering an alternative. I looked at Moles before, and tried to use it. But for some reason, I disliked the mechanism of creating these files with the ‘M’ prefix. It felt like a lot of non-obvious junk to me. But as you say, each mocking framework has its learning curve. What you show above is essentially the same as what I would put into a fake class. But Moles lets you fake the static method. I can only make useful fake classes for classes that implement an interface. And I certainly cannot fake static methods since those cannot be represented in an interface. I admit that the ability to mock non-virtual and static methods is really powerful for cases where I do not have full control over the classes involved. I don’t mind refactoring my own code to make it mockable. But if I have something beyond my control, then I want all the tools I can get. Otherwise, I have to wrap the hard-to-mock classes in an adapter, and create an interface for the adapter, and code to that interface, blah, blah, blah.

I will take one more look at Moles and try the example above to see what my annoyance was. I am older and wiser this year, than I was last year 🙂 So maybe I will feel differently.

Oh, and I found an annoying defect in the SetupSequence. It can return nice things and end in throwing an exception. But it will not let me throw the exception first, followed by normal operations. That is essential in testing retry logic, where you want to have a failure, which the retry logic overcomes. So I ended up removing the SetupSequence, and creating a fake class anyway that uses the same sort of design you show, where it varies it’s behavior with the callCount. I’ll try the Moles approach and see which one is more readable. I want it to be clear to my colleagues who may find it after me.

Moles is not without its warts. Some of the design decisions are a little weird, but logical enough. You mentioned the “M” on front of the mole classes. That’s weird but very easy to understand and work with. The best thing about Moles is that I never have to change existing code and I can mock anything.

I work with a number of developers that would like to do more unit testing but haven’t done much in the past and have no idea what a mock is. Luckily, they had already used lambda expressions so all I had to teach them was the how to create the mole. It was very cool to see their eyes light up as they saw they could now test legacy code that wasn’t unit testable before.

MOQ is definitely my second favorite mocking framework. It’s just unusable for the application I’m testing.

Along the same lines of “simplicity”, I build an Assertion framework at http://jslmstesthelper.codeplex.com/. All the current Assertion frameworks makes you build non-intuitive to test values:
Assert.Equal(2, value);
If you think about it, it would be much easier to teach developers something like this:
Assert(value == 2);
My framework uses lambda expressions for this. You would write the above as:
AssertEx.That(() => value == 2);
I don’t like the extra lambda expression stuff, but that’s as clean as I could get it. I use the expression tree from the lambda expression to figure out that the developer wants to compare “value” and “2”. My framework compares them and can give a failure message like “Expected value to be 2.”

I believe there is another project for assertions that uses Cecil to rewrite Assert statements to produce better failure messages. My stuff was good enough so I didn’t look into more.

My baby is waking up so I have to go feed her. Hopefully I didn’t make any horrible typos in the above. 🙂

Thanks for the encouragement. If you had not spoken highly of it, I might have given up on the tutorial. I should learn by now to go slowly through those things and do them EXACTLY as written. When I used MFileSystem to mock my custom static class, I was impressed.
When I used MFile to mock a static method on a corlib class, embedded several layers into something, where I could never inject something, then I was REALLY impressed. I can see this will be powerful for APIs that are still primitive and not designed to interfaces.

Make sure you check out Pex as well. Based on a unit test that takes parameters, it will find the parameter values that cover the most code possible. It took me a while to wrap my brain around to using it, and I still only use it a percentage of the time, but it’s pretty cool for certain kinds of tests.

Thinking about MFile (or any such class) and using interfaces instead, there are times when you know you aren’t going to ever have more than one interface. In those cases, building an interface is just putting a layer of indirection into your code. I’ve taken to using the real classes (such as File) and using Moles to unit test. Of course it would be stupid to do that 100% of the time. In a little side project I’m working on I am using a interface for the file system, but that is because I want to use the same interface for getting files from source control and from the file system.

Regarding coding to concrete classes as a default position – that is interesting. Our mantra has been “code to interfaces” so long, that I must reflect on that. As you say, if it is so easy to mock the concrete class, then why would we want the interface? If we need it, for example, to support multiple implementations, then by all means, write an interface. But, as you say, in cases where there is only one implementation, it might be easier to skip the interface. It’s easy enough to refactor it later. And with a tool like JetBrain’s ReSharper, I can issue one command to convert the concrete usages to interfaces everywhere. And I do not see any conflict with TDD either.