6

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); 
albertjan
  • 7,739
  • 6
  • 44
  • 74
  • 1
    What "doesn't work"? – Gert Arnold Jan 19 '15 at 19:39
  • @GertArnold The property `x.Provider` cannot be accessed (because it is an explicit interface implementation) - I think the question is quite clear. – Tomas Petricek Jan 19 '15 at 19:45
  • How do I explain this. I know the provider is an indispensable part of a `DbSet`, but you'll never access it in application code. So you don't want to unit test it. Still something must have triggered you to try and mock it, which is this something that "didn't work". – Gert Arnold Jan 19 '15 at 19:54
  • @GertArnold see: http://msdn.microsoft.com/nl-nl/data/dn314429.aspx#queryTest – albertjan Jan 19 '15 at 19:55
  • 1
    @albertjan implementing multiple interfaces is not supported in Foq 1.6. I've now added an As method to handle this scenario which should be available in the next release. – Phillip Trelford Mar 02 '15 at 22:33

1 Answers1

5

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())
Phillip Trelford
  • 6,513
  • 25
  • 40