Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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); 
like image 847
albertjan Avatar asked Jan 19 '15 13:01

albertjan


1 Answers

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())
like image 61
Phillip Trelford Avatar answered Sep 30 '22 15:09

Phillip Trelford