Search code examples
f#fakeiteasy

FakeItEasy - Invokes with option member arguments in F#


When attempting to supply a fake delegate for a method with an optional parameter in a faked object

type MyType () = 
    abstract B: ?s:string -> unit
    default x.B (?s: string) = Option.iter (printfn "Implemented: %s") s

[<Property>]
let doit () = 
    let a = A.Fake<MyType>()
    A.CallTo(fun () -> a.B(ignored())).Invokes(fun s -> Option.iter (printfn "Faked: %s") s)
    a.B "Hello"

FakeItEasy complains

FakeItEasy.Configuration.FakeConfigurationException: Argument constraint is of type System.String, but parameter is of type Microsoft.FSharp.Core.FSharpOption`1[System.String]. No call can match this constraint.

Is there a way to make this run without changing the type definition ?


Solution

  • OK, I was able to reproduce your error message by defining ignored as:

    let ignored<'t> () = A<'t>.Ignored
    

    The problem is that you've defined a string constraint for an argument that's actually a string option. You can work around this by explicitly naming the parameter ?s when you call the member, like this:

    A.CallTo(fun () -> a.B(?s=ignored())).Invokes(fun s -> Option.iter (printfn "Faked: %s") s)
    

    Now the constraint has the correct type, Option<string>, and the code executes without error. Output is:

    Faked: Hello
    

    This SO answer has more details about specifying values for optional arguments.