# WoofWare.Whippet.Plugin.InterfaceMock
This is a [Whippet](https://github.com/Smaug123/WoofWare.Whippet) plugin for defining mocks for interfaces.
It is a copy of the corresponding [Myriad](https://github.com/MoiraeSoftware/myriad) HttpClient plugin in [WoofWare.Myriad](https://github.com/Smaug123/WoofWare.Myriad), taken from commit d59ebdfccb87a06579fb99008a15f58ea8be394e.
## Usage
Define a file like `Client.fs`:
```fsharp
type IPublicType =
abstract Mem1 : string * int -> string list
abstract Mem2 : string -> int
```
In your fsproj:
```xml
Client.fs
InterfaceMock
```
(This plugin follows a standard convention taken by `WoofWare.Whippet.Plugin` plugins,
where you use Whippet parameters with the same name as each input type,
whose contents are a `!`-delimited list of the generators which you wish to apply to that input type.)
The generator produces a type like this:
```fsharp
/// Mock record type for an interface
type internal PublicTypeMock =
{
Mem1 : string * int -> string list
Mem2 : string -> int
}
static member Empty : PublicTypeMock =
{
Mem1 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
Mem2 = (fun x -> raise (System.NotImplementedException "Unimplemented mock function"))
}
interface IPublicType with
member this.Mem1 (arg0, arg1) = this.Mem1 (arg0, arg1)
member this.Mem2 (arg0) = this.Mem2 (arg0)
```
### What's the point?
Reflective mocking libraries like [Foq](https://github.com/fsprojects/Foq) in my experience are a rich source of flaky tests.
The [Grug-brained developer](https://grugbrain.dev/) would prefer to do this without reflection, and this reduces the rate of strange one-in-ten-thousand "failed to generate IL" errors.
But since F# does not let you partially update an interface definition, we instead stamp out a record,
thereby allowing the programmer to use F#'s record-update syntax.
### Features
You may supply an `isInternal : bool` argument:
```xml
Client.fs
InterfaceMock(false)
```
By default, we make the resulting record type at most internal (never public),
since this is intended only to be used in tests;
but you can instead make it public by setting the `false` boolean.