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