Object expressions are a cool feature of F#. For those unfamiliar, they allow you to easily instantiate anonymous classes:
let mutable disposed = false
let anonomousType =
{ new IDisposable with
member this.Dispose() =
disposed <- true }
Assert.IsTrue(disposed)
There are times when it’s useful to instantiate anonymous classes in this fashion (a topic for another post), but I’m not convinced that mocking is one of them. However, based on based on a couple of twitter conversations that I’ve had with notable F# community members Richard Minerich and Steffen Forkmann, my opinion may be in the minority. I understand their opinions in theory, but in practice, I find that object expressions are inferior to Mocking Libraries for generating mock objects.
I will go over a few advantages of mocking libraries below, but before I do that, I would like to define what I mean by “mock object” in this post. The term “mock” is a loaded one in the testing world, and it seems like everyone has their own opinion about what the words mock, dummy, stub, spy, fake, and test double actually mean. I’m far less dogmatic about this. For the rest of the post, consider a mock to be any object that takes the place of another for the purpose of testing.
Abstraction vs Verbosity
In his tweet, Steffen says that he believes object expressions are much clearer than mock libraries. On one hand, I understand his reasoning; mock libraries use more abstraction than object expressions, and abstraction can make code more difficult to understand. Ironically, I find this argument to be very similar to one that I often hear from people who favor for loops over the use of LINQ or higher order functions like that in the F# Seq module. They prefer the verboseness of a for loop to the abstraction of a library function.
I often use a simple example to explain the advantages of the F# Seq module over for/foreach loops. The goal is to find the sum of the squares of the even numbers less than or equal to ten.
IEnumerable<int> values = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
int sum = 0;
foreach (int value in values)
{
if (IsEven(value))
{
sum += Square(value);
}
}
Assert.AreEqual(220, sum);
let numbers = [0..10]
let sum =
numbers
|> List.filter IsEven
|> List.map Square
|> mySum
I don’t know any functional programmer who would argue that the for/foreach loop is clearer than the version using the List module. They understand and accept the abstraction of higher order functions, so the abstraction actually adds clarity to the code.
Now lets consider a typical testing scenario. Given a dummy interface, IFoo:
type IFoo =
abstract foo: int -> int
The goal is to create a mock IFoo that validates that foo was called and also returns a dummy value for foo.
First is a F# solution with object expressions:
let mutable wasCalled = false
let mock =
{ new IFoo with
member this.foo x =
wasCalled <- true
0 }
let result = aFunctionThatDependsOnIFoo(mock)
Assert.IsTrue(wasCalled)
Assert.AreEqual("the expected value", result)
Now here’s a C# implementation using MOQ:
var mock = new Mock<IFoo>();
mock.Setup(f => f.foo(It.IsAny<int>())).Returns(0);
var result = aFunctionThatDependsOnIFoo(mock.Object);
mock.Verify(f => f.foo(It.IsAny<int>()), Times.Once());
Assert.AreEqual("the expected value", result);
Like the List module in the first example, MOQ encapsulates the logic required to create mock objects into helper functions, and like the foreach loop, the object expression puts all of that wiring in the test. Code like the foreach loop and object expression is simple to read and write, but it’s code that a library can and should take care of. By factoring out the common bits into a helper library, your code becomes less error prone, less brittle, and easier to maintain. As with LINQ and the Seq/List module, mocking frameworks require that you accept and understand a small degree of abstraction, but it’s the abstraction that makes your code more clear.
Scalability
Object expressions are manageable for small interfaces, but they quickly become unwieldy if you want to mock an interface that contains multiple methods. For example, let’s say you want to mock a method on an interface with 4 methods using object expressions:
type IFoo2 =
abstract foo1: int -> int
abstract foo2: int -> int
abstract foo3: int -> int
abstract foo4: int -> int
let mock =
{ new IFoo2 with
member this.foo1 x =
0
member this.foo2 x =
0
member this.foo3 x =
0
member this.foo4 x =
0 }
That’s a lot of work to just mock one method one time. IFoo2 doesn’t have any complicated method signatures, and you aren’t even validating that methods are called. With a mocking library, all of that work is accomplished in two lines of code.
var mock = new Mock<IFoo2>(); mock.Setup(f => f.foo1(It.IsAny<int>())).Returns(0);
Maintainability
Let’s say that you’re using the IFoo2 interface in a production codebase with a few hundred tests. Now the requirements change and you need to add a new method to IFoo2. With the object expression syntax, you have to go through and change every object expression to add a default implementation for that method. Even if you don’t have a separate mock object for every test, it’s still a lot of overhead for a relatively small change. With mocking library, you don’t have to change any of your code. All of your tests work the same way they did before, and you can focus on the task at hand instead of maintaining your tests.
Closing Thoughts
Object expressions are a little better than creating a new type every time you want to mock, but I think the above arguments apply in both cases. I don’t know many C# developers who prefer hand rolling new mock classes to mocking libraries, and I don’t understand what makes object expressions different. That being said, I know there are some great F# coders who have a different opinion, so I would love to hear the other side of the story via comments, twitter, a fierce blog-off, etc. : )
I should also point out that while I love MOQ for creating mock objects in C#, I wouldn’t recommend it for use from F#. It relies heavily on LINQ expressions which are difficult to create via F#, and even in the best case, it pollutes your code with a lot of quotations. I would gladly pay someone a shiny quarter if they would write an F# wrapper over MOQ or (even better) a mocking library specifically targeted for F#.
5 Reasons to use F# Interactive in Visual Studio 2010
1) You already have it
F# comes standard with Visual Studio 2010, and it includes F# Interactive. There’s nothing to install, and no configuration is required. You don’t even need to start a F# project in order to use FSI. From anywhere inside Visual Studio, select View | F# Interactive, or just press Ctrl + Alt + F to bring up an FSI instance.
2) Performance Analysis
With the #time option enabled, F# Interactive is a surprisingly useful tool for performance analysis. A few days ago, coworkers Jay Wren and Ben Barefield asked me to help determine why a LINQ statement they wrote was running slowly. After spending time looking over the code and running it through a profiler, we wanted to see how LINQ’s distinct statement behaved with different inputs. Within a couple minutes, I was able to get information using F# Interactive.
First, I wrote a simple setup script:
Then I ran couple of statements to test timing:
F# Interactive is no substitute for more sophisticated performance analysis techniques, but when it comes to getting fast answers to test bottlenecks, it’s a great tool to have at your disposable.
3) Verifying the Behavior of Base Class Library Functions
There are a lot of APIs in the Base Class Library, and it can be tough to remember exactly how everything works. Let’s say you can’t remember if the Insert function on List<T> inserts elements before or after the input index. You could write a small console application or a throwaway test to verify the behavior, but it’s a lot faster to use FSI:
4) Learning F# and Functional Programming
Learning any language teaches you new coding techniques. Learning a functional language teaches you new problem solving techniques. F# Interactive lets you do both without leaving Visual Studio or closing your open project. Whenever you have a few minutes to kill during development, you can easily open a FSI window and play around with F#. You can also use it to deep dive and explore syntax and techniques with a more extended session. Finally, using F# Interactive while programming in another .NET language is a great way to keep your F# skills sharp even if you aren’t writing F# on a daily basis.
5) Spikes and Scripting
This is probably the first use case that people think of when they see FSI (or other REPLs). In practice, I find that I use F# Interactive more for performance analysis, learning F#, and verifying Base Class Library behavior than for spiking or scripting. However, it’s worth pointing out that F# Interactive is a powerful tool for quickly exploring problem domains. By creating script files, you can build up situations to evaluate different approaches without investing a lot of time setting up a dummy project or a clumsy test harness.