1

I am trying to use Foq to testing an interface with Foq.

So far, all examples I have seen for this have been relatively simple, such as the following:

let users = [|{ID = 1; pass = true};{ID = 2; pass= false}|]

type IFoo = 
    abstract member Bar: int -> bool

//tests with Foq
let dataAccess = 
    Mock<IFoo>()
    .Setup(fun x-> <@ x.Bar(users.[0].ID)  @>).Returns(users.[0].pass)
    .Setup(fun x-> <@ x.Bar(users.[1].ID)  @>).Returns(users.[1].pass)
    .Create()

The examples have been sourced from 'Testing with F# - Mikael Lundin'

I have also researched this through a bit of googling (this link was helpful - http://trelford.com/blog/post/Foq.aspx)

However, the real Interfaces I want to test are the following:

type IParameters =
    abstract member ParameterDate : int->string->DateTime 

type IDataSource =
    abstract member MortParameters: IParameters

I have tried a number of different ways to test these (e.g. defining a function with a signature of int->string to be used as the input to the setup. Alternatively, having the return value as a string->DateTime and the Setup as just an integer.

My question is really the following: When testing interfaces using Foq, how can I extend the testing to interfaces with function signatures of any general length (e.g. a->b->c->d->e etc.)

Pash101
  • 631
  • 3
  • 14
  • Are we not usually supposed to define interface and class members in tupled form? Would your problem then still exist if you wrote: ``abstract member ParameterDate : (int * string) -> DateTime``? – BitTickler May 08 '16 at 14:03
  • Good point and likely not. However, I am adding unit tests to a pre-built system (someone else's code). It would likely be a considerable piece of work to re-engineer all interfaces to be like this. Also, some of the interface signatures are relatively long, hence you would need 5 or 6 element tuples. – Pash101 May 08 '16 at 14:07

1 Answers1

0

Since ParameterDate a property with a function type, you could just set it up as a property that returns a lambda value. See an example of property set-up in Foq. This should be easy to modify for your case:

let instance =
    Mock<System.Collections.IList>()
        .Setup(fun x -> <@ x.Count @>).Returns(1)
        .Create()

However, I guess you would lose the ability to have a strict mock with fixed expectations on the function inputs.


To enforce only expected inputs for the function returned by the mock property you could provide a function like this:

fun i s ->
    match i, s with
    | 1, "" -> DateTime.Now
    | _ -> failwith "Invalid mock input"

I would probably stop here, but if you're working with code where you need to verify a function was called, as opposed to just ensuring you get the correct output, you could add a helper like this:

type Verifiable<'a, 'b> (f : 'a -> 'b) =
    let called = ref false
    member this.Func x =
        called := true
        f x
    member this.Verify() =
        if not called.Value then failwith "Mock function was not called"

And here's how you would use it:

let parameterDateMock =
    fun i s ->
        match i, s with
        | 1, "" -> DateTime.Now
        | _ -> failwith "Unexpected mock input"
    |> Verifiable

let parameters =
    { new IParameters with member this.ParameterDate i s = parameterDateMock.Func i s }

parameters.ParameterDate 1 ""

parameterDateMock.Verify()

Caveat: This only verifies the function was called with at least one parameter. It may have returned another function by currying and not actually run the code in the mock function body. To get around that you'd need a variation of the Verifiable class for every function arity and use the right one in each case.

TheQuickBrownFox
  • 10,544
  • 1
  • 22
  • 35