F# mock library based on Rhino.Mocks
Switch branches/tags
Nothing to show
Clone or download
Fetching latest commit…
Cannot retrieve the latest commit at this time.
Permalink
Failed to load latest commit information.
.nuget
Tests
.gitignore
AssemblyInfo.fs
FsMocks.fsproj
FsMocks.nuspec
FsMocks.sln
README.md
Syntax.fs
appveyor.yml
nuget-package.bat
packages.config

README.md

FsMocks / FsharpMocks

F# mock library

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

Build 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