FsMocks / FsharpMocks
FsMocks is an object mocking library written in F#. It is actually a wrapper around Rhino.Mocks 3.6 that simplifies mocking with F#. The API is simple and straightforward because it uses a human-friendly DSL syntax. It can be combined with other test frameworks (NUnit, xUnit, FsUnit, etc.)
Project status
NuGet
Get the latest package here. This package is compiled against F# 3.0. If you wish to use F# 3.1, download and compile the source code.
Samples
This sample creates a new IList and expects calls to the methods Add() and Clear(), in any order, but with some constraints.
open System.Collections open FsMocks.Syntax // create mock object and repository use mock = new FsMockRepository() // use the keyword 'let' instead of 'use' if you don't want automatic verification (But why would you want that anyway?) let mylist1:IList = mock.strict [] // define mock statements mock.define Unordered { ~~ mylist1.Add "e" |> returns 2 |> expected once |> only_if_argument [Is.NotNull()] ~~ mylist1.Clear() |> expected twice } // run test. mylist1.Clear() mylist1.Add("another argument") |> should equal 2 // FsUnit syntax mylist1.Clear() // FsMocks will automatically verify expectations at the end of the test. The test will fail if any unexpected call was made
A mock definition can either be Unordered or Ordered. It takes a series of mock statements.
A mock statement begins with ~~, followed by the call or property to mock, followed by mock directives:
// the call is expected twice ~~ o.call() |> expected twice // the mock object will return 219 when this expectation is satisfied ~~ o.call("some arg") |> returns 219 // the call is expected only if it respects the given constraints ~~ o.call(arg) |> only_if_argument [Is.NotNull()] // Property1 will be implemented as a simple get/set property ~~ o.Property1 |> implement_as_property // the most powerful statement : the call is manually implemented let myCustomClearImplementation() = System.Console.WriteLine("list cleared!!!") ~~ list.Clear() |> implement_as (new Action(myCustomClearImplementation)) // throws an exception whenever a method is called ~~ o.call() |> throws (new Exception("Something went wrong!!")) // subscribe to an event and simulate an event let b:Button = mock.strict [] let clickRaiser = mock.getEventRaiser(b.Click) mock.define Ordered { b.Click |> subscription expected once } b.Click |> Event.add (fun _ -> System.Console.WriteLine "clicked!" ) clickRaiser.Raise(b, new EventArgs()) // this prints "clicked!"
Mock directives can be combined in no particular order, except for the returns directive which must be on the first position.
~~ o.Call(1) |> returns 1 |> only_if_argument [Is.NotNull()] |> expected at_least_once
Mock definitions can be nested:
let [<Fact>] ``1b) 2 Ordered nested in 1 Unordered``() = // create mocks use mock = new FsMockRepository() let list:int IList = mock.strict [] // mock definition mock.define Unordered { mock.define Ordered { ~~ list.Add(1) |> expected once ~~ list.Add(2) |> expected once } mock.define Ordered { ~~ list.Add(3) |> expected twice ~~ list.Contains(5) |> returns true |> expected once } } // run test list.Add(3) list.Add(3) Assert.True(list.Contains(5)) list.Add(1) list.Add(2) // verify expectations