Search code examples
c#entity-frameworkf#mockingfoq

Mocking a class with an explicitly implemented interface using Foq


I wanted to mock an entityframwork DbSet using Foq. It goes something like:

let patients = 
    ([
        Patient(Guid "00000000-0000-0000-0000-000000000001");
        Patient(Guid "00000000-0000-0000-0000-000000000002");
        Patient(Guid "00000000-0000-0000-0000-000000000003");
    ]).AsQueryable()

let mockPatSet = Mock<DbSet<Patient>>.With(fun x ->
    <@ 
        // This is where things go wrong. x doesn't have a property Provider
        x.Provider --> patients.Provider 
    @>
)

I tried coercing and casting x to an IQueryable at some places but that doesn't work.

As you can see here in the docs for DbSet it does implement the IQueryable interface via DbQuery, but does so by "explicitly" implementing the properties.

In Moq there is a Function As so you can tell it to treat it as a IQueryable that looks like:

var mockSet = new Mock<DbSet<Blog>>(); 
mockSet.As<IQueryable<Blog>>().Setup(m => m.Provider).Returns(data.Provider); 

Solution

  • The latest release of Foq (1.7), now supports implementing multiple interfaces using a Mock.As method, similar to the setup in Moq, e.g.

    type IFoo = 
        abstract Foo : unit -> int
    
    type IBar =
        abstract Bar : unit -> int
    
    [<Test>]
    let ``can mock multiple interface types using setup`` () =
        let x = 
            Mock<IFoo>().Setup(fun x -> <@ x.Foo() @>).Returns(2)
             .As<IBar>().Setup(fun x -> <@ x.Bar() @>).Returns(1)
             .Create()    
        Assert.AreEqual(1, x.Bar())
        Assert.AreEqual(2, (x :?> IFoo).Foo())