嘲笑多个接口wirth machine.fakes

时间:2015-01-13 17:37:17

标签: entity-framework-6 nsubstitute machine.fakes

如何获得

的等价物
Substitute.For<DbSet<MyClass>, IQueryable<MyClass>, IDbAsyncEnumerable>()

使用machine.fakes? 我尝试使用

var myFake = An<DbSet<MyClass>>();
myFake.WhenToldTo(m => ((IQueryable<MyClass>)m).Provider).Return(whatever);

但是我得到以下NotImplementedException:

The member 'IQueryable.Provider' has not been implemented on type 'DbSet`1Proxy' which 
inherits from 'DbSet`1'. Test doubles for 'DbSet`1' must provide implementations of 
methods and properties that are used.

同样的异常引起了人们的注意     myFake.WhenToldTo(m =&gt;((IQueryable)m).Provider)。返回(无论如何);

这是一个用最少的代码重现问题的类。 您需要为Entity Framework,Machine.Specifications,Machie.Specifications.Should,Machine.Fakes,Machine.Fakes.NSubstitute,NSubstitute(或任何其他Mock Framework插件)添加包

using System.Data.Entity;
using System.Linq;
using Machine.Fakes;
using Machine.Specifications;

namespace SpecsTests
{
    public class TestClass
    {}

    [Subject("Test")]
    internal class TestSpecifications
    {
        [Subject("Test")]
        private class Test : WithFakes
        {
            private static int Count;
            private static DbSet<TestClass> Subject;

            private Establish context = () =>
                                        {
                                            var data = new [] { new TestClass() }.AsQueryable();
                                            Subject = An<DbSet<TestClass>>();

                                            Subject.WhenToldTo(m => ((IQueryable)m).Provider).Return( data.Provider);
                                        };

            private Because of = () => { Count = Subject.Count(); };

            private It Should_return_expected_results = () =>
                                                        {
                                                            Count.ShouldEqual(1);
                                                        };

        }
    }
}

1 个答案:

答案 0 :(得分:1)

使用Machine.Fakes无法伪造一个假人中的多个界面 - 相当于NSubstitute的Substitute.For<>()。 我看到了两个选项:

  1. 直接使用NSubstitute 你总能做到 Subject = Substitute.For<DbSet<TestClass>, IQueryable<TestClass>>();
    而不是 Subject = An<DbSet<TestClass>>();
    缺点是你放弃了底层模拟框架和Machine.Fake的自动插锁功能的独立性

  2. 重构代码,一次只伪造一个界面。这将是我的首选方案 我对此的第一次尝试是伪造IDbSet<>而不是DbSet<>,并且只针对此接口。但是,我知道你想要实现的目标太少,无法提供更详细的提示。作为一般规则,您应该始终尝试依赖接口。也许你可以让受测试的课程独立于具体的DbSet<>