Phillip Trelford's Array

POKE 36879,255

Mocking with Foq

Foq is an open source .Net mocking library with a familiar fluent API for Moq users that lets you setup mock object using either LINQ or F# Code Quotations. Moq was developed to take advantage of .Net 3.5 LINQ expression trees and C# 3.0 features. Foq has been designed to provide first-class support for users of both C# and F#. C# users can use the LINQ API while F# users can choose between the LINQ API and Code Quotations. We use F# as a unit testing language at work and Foq for mocking code written in both C# and F#.

Examples

Setup a mock method in C# with a lambda expression:

new Mock<IList<int>>()
    .SetupFunc(x => x.Contains(It.IsAny<int>())).Returns(true)
    .Create();

Setup a mock method in F# with a Code Quotation:

Mock<System.Collections.IList>()
    .Setup(fun x -> <@ x.Contains(any()) @>).Returns(true)
    .Create()

Setup a property in C# with a lambda expression:

new Mock<IList<int>>()
    .SetupPropertyGet(x => x.Count).Returns(1)
    .Create();

Setup multiple properties in C# with an anonymous object:

new Mock<IOrder>()
    .SetupProperties(new {
        Price = 99.99M,
        Quantity = 10,
        Side = Side.Bid,
        TimeInForce = TimeInForce.GoodTillCancel
    })
.Create();

Setup multiple members in F# with a Code Quotation:

Mock<IList<char>>.With(fun xs ->
    <@ xs.Count --> 2 
        xs.Item(0) --> '0'
        xs.Item(1) --> '1'
        xs.Contains(any()) --> true
        xs.RemoveAt(2) ==> System.ArgumentOutOfRangeException()
    @>
)

Verify a method was called in C#:

Mock.VerifyFunc(() => list.Contains(1));

Verify a method was called once in F#:

Mock.Verify(<@ xs.Contains(any()) @>, once)

Download

Foq is available on Nuget or for F# projects you can just include the Foq.fs source file.

Moq with F# 3

F# 3 has LINQ expression support built-in just like C# and VB.Net. Prior to this basic LINQ expression interop could be achieved with the F# PowerPack and F# Code Quotations.

F# 3 LINQ support opens up APIs that use LINQ expressions like Moq, a popular .Net mocking library. With some minor workarounds Moq is relatively easy to call from F#.

C# Moq example:

var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);

F# requires a type annotation:

TypeAnnotation

F# requires the return value to be explicitly ignored:

UseIgnore

F# Moq example with required type annotation and return value piped to ignore:

let mock = Mock<IFoo>()
mock.Setup<bool>(fun foo -> foo.DoSomething("ping")).Returns(true) |> ignore

The type annotation is required as the Setup method provides multiple overloads with differing generic parameters. Another way to workaround this is to write specific extension methods for overloads:

type Moq.Mock<'T> when 'T : not struct with
  /// Specifies a setup on the mocked type for a call to a function
  member mock.SetupFunc<'TResult>(expression:Expression<Func<'T,'TResult>>) =
    mock.Setup<'TResult>(expression)
  /// Specifies a setup on the mocked type for a call to a void method
  member mock.SetupAction(expression:Expression<Action<'T>>) = 
    mock.Setup(expression)
  /// Specifies a setup on the mocked type for a call to a property setter
  member mock.SetupSetAction<'TProperty>(setupExpression:Action<'T>) 
    : Moq.Language.Flow.ISetupSetter<'T,'TProperty> = 
    mock.SetupSet<'TProperty>(setupExpression)

The ignore statement is required as F# requires return values to be handled explicitly. Moq’s fluent inteface provides some methods where the return value is ignorable.

The issues using Moq’s API from F# 3 can be fairly easily worked around. That said for an API designed specifically for F# consider using Foq which has similar functionality to Moq and supports both Code Quotations and LINQ expressions. You may also find F#’s built-in Object Expressions sufficient for many tasks.

F# as a Unit Testing Language

I’ve found writing unit tests in F# very productive, with it’s terse syntax and powerful type inference. I write F# tests against C# and F# implementations.

Writing tests in F# can be a good introduction to the language and this is something we do on our team. To get up to speed quickly you’ll typically want a familiar unit testing framework and mocking library syntax.

F# code works with all the popular open source .Net unit testing frameworks:

…it also works with Microsoft’s Visual Studio Unit Test Framework.

F# unit tests can be run inside Visual Studio using TestDriven.Net, ReSharper and NCrunch.

Backticks

F# lets you write function names with white space inside double backtick marks (``):

let [<Test>] ``1 + 1 should equal 2`` () =
    Assert.AreEqual(1 + 1, 2)

This feature alone can make your unit tests easier to read and write.

Void

In C# the return value of a method can be implicitly ignored. In F# return values must be explicitly handled. Simple test functions are typically expected to return nothing, so in F# you need to be careful that you don’t inadvertently return a value, for example NUnit’s Assert.Throws returns the specified exception which you can pipe to ignore. Or you can extend the Assert class with a Raise method that ignores the return value.

module Assert =
    /// Verifies that a delegate raises the specific exception when called.
    let Raises<'TExn when 'TExn :> exn> (f:unit->unit) = 
        Assert.Throws<'TExn>(TestDelegate(f)) |> ignore

F# Object Expressions

F# Object Expressions let you implement an interface without the need to create a new class. This can be useful for simple mocking scenarios:

let comparer = { new IComparer<_> with member x.Compare(l,r) = l - r }

This works well for small interfaces but does not scale well to larger or changing interfaces as all members must be implemented:

let list = 
    { new IList<_> with
        member __.Count = 1
        member __.Insert(_,_) = raise <| NotImplementedException()
        member __.IndexOf(_) = raise<| NotImplementedExcpetion()
        // ...
    }

.Net Mocking libraries

F# works well with many of the major .Net mocking libraries like Rhino.Mocks and NSubstitute. Built-in support for LINQ expression trees used in libraries like Moq was introduced recently with F# 3.0 in Visual Studio 2012. For F# 2.0 in Visual Studio 2010 the F# PowerPack is required which can be a bit fiddly.

Foq

Foq is an F# mocking library similar to Moq that parses F# Code Quotations, making it compatible with F# 2.0/3.0 and .Net 2.0/3.5/4.0/4.5.

Moq C# Method:

var mock = new Mock<IFoo>();
mock.Setup(foo => foo.DoSomething("ping")).Returns(true);
var instance = mock.Object;

Foq F# Method:

let foo = Mock<IFoo>()
            .Setup(fun foo -> <@ foo.DoSomething("ping") @>).Returns(true)
            .Create()

Moq C# Matching Arguments:

mock.Setup(foo => foo.DoSomething(It.IsAny<string>())).Returns(true);

Foq F# Matching Arguments:

mock.Setup(fun foo -> <@ foo.DoSomething(any()) @>).Returns(true)

Moq C# Property:

mock.Setup(foo => foo.Name ).Returns("bar");

Foq F# Property:

mock.Setup(fun foo -> <@ foo.Name @>).Returns("bar")

Summary

Unit testing, including mocking, is well supported in F#. If you are a .Net developer you should find the experience familiar and perhaps a good opportunity to pick up a new language.

Further reading