1

I need to mock a DbSet with RhinoMock. I found a way to mock IDbSet, but not DbSet. I found a way with another mocking framework, but i have to use RhinoMock. Can somebody please translate it to rhino mock?

I found this on http://www.loganfranken.com/blog/517/mocking-dbset-queries-in-ef6/:

private static DbSet<T> GetQueryableMockDbSet<T>(params T[] sourceList) where T : class
{
   var queryable = sourceList.AsQueryable();

   var dbSet = new Mock<DbSet<T>>();
   dbSet.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryable.Provider);
   dbSet.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryable.Expression);
   dbSet.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryable.ElementType);
   dbSet.As<IQueryable<T>>().Setup(m => m.GetEnumerator()).Returns(() => queryable.GetEnumerator());

   return dbSet.Object;
}

Thanks

Dosihris
  • 85
  • 1
  • 8

1 Answers1

0

Update

While RhinoMocks supports mocking multiple interfaces with the same mock, as I utilized in my initial answer, it apparently doesn't support explicit intefaces, which DbSet utilizes for IQueryable. As @Dosihris pointed out in the comment, it throws an exception saying

Due to how CLR handles explicit interface implementation, we're not able to proxy this method.

This appears to be an exception from the version of Castle.DynamicProxy (v2.1.0.5967) embedded in RhinoMocks, which is from pre-2010. Newer versions of DynamicProxy support this, so if you really wanted to be adventurous, you could recompile RhinoMocks with an updated version of DynamicProxy.

Or, you could try referencing DynamicProxy directly in your test project and using binding redirects to force RhinoMocks to use the newer version. Given the age of the version in RhinoMocks, there's likely incompatibilities with the newer DynamicProxy APIs, so this is likely not going to be successful.

Or, you could move to a framework that is still actively maintained, such as Moq or NSubstitute (which both use newer versions of DynamicProxy).


This is the equivalent logic using RhinoMocks:

using Rhino.Mocks;

private static DbSet<T> GetQueryableMockDbSet<T>(params T[] sourceList) where T : class
{
    var queryable = sourceList.AsQueryable();

    var dbSet = Rhino.Mocks.MockRepository.GenerateMock<DbSet<T>, IQueryable<T>>();

    ((IQueryable<T>)dbSet).Expect(m => m.Provider).Return(queryable.Provider);
    ((IQueryable<T>)dbSet).Expect(m => m.Expression).Return(queryable.Expression);
    ((IQueryable<T>)dbSet).Expect(m => m.ElementType).Return(queryable.ElementType);
    ((IQueryable<T>)dbSet).Expect(m => m.GetEnumerator())
            .Return(null) // will be ignored but still the API requires it
            .WhenCalled((methodInvokation) =>  methodInvokation.ReturnValue = queryable.GetEnumerator());

    return dbSet;
}

Depending on whether you want to do verification that the properties were called or not, you may want to use .Stub() instead of .Expect() in each of the above.

John M. Wright
  • 4,477
  • 1
  • 43
  • 61
  • Hey John, thank you, but unfortunately i get an exception. Castle.DynamicProxy.ProxyGenerationException at var dbSet = Rhino.Mocks.MockRepository.GenerateMock, IQueryable>(); with message: Due to how CLR handles explicit interface implementation, we're not able to proxy this method. – Dosihris Jul 09 '17 at 10:11
  • It looks like it may not be possible with RhinoMocks. Unfortunately, that project is no longer actively maintained, so it's fallen behind on functionality. You mentioned that you have to use RhinoMocks -- keep in mind that RhinoMocks can be used along side Moq and other Frameworks in the same project (but you can only use one or the other within a given mock). – John M. Wright Jul 09 '17 at 15:39
  • Hey John, thanks, that was helpfull, i didnt know that rhino mocks is no longer supported. i currently use a mix of Rhino and NSubstitute. I actually mixed the mocks, and it works. Thanks, have a nice day, Nico – Dosihris Jul 09 '17 at 19:59