Издеваться над несколькими интерфейсами с 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 => ((IQueryable)m).Provider).Return(что угодно);

Это класс, который воспроизводит проблему с минимальным кодом. Вам необходимо добавить пакеты для 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 ответ

Решение

Невозможно подделать более одного интерфейса в одной подделке с помощью Machine.Fakes - эквивалентно NSubstitute's Substitute.For<>(), Я вижу два варианта для вас:

  1. Используйте NSubstitute напрямую.
    Вы всегда можете сделать
    Subject = Substitute.For<DbSet<TestClass>, IQueryable<TestClass>>();
    вместо
    Subject = An<DbSet<TestClass>>();
    Недостатки заключаются в том, что вы отказываетесь от независимости от базового фреймворка и возможностей автозамены Machine.Fake.

  2. Реструктурируйте свой код, чтобы имитировать только один интерфейс за раз. Это был бы мой предпочтительный вариант.
    Моя первая попытка с этим была бы подделка IDbSet<> вместо DbSet<> и работать только против этого интерфейса. Однако я слишком мало знаю о том, чего вы пытаетесь достичь, чтобы дать более подробные советы. Как правило, вы всегда должны зависеть от интерфейсов. Может быть, вы можете сделать тестируемый класс независимым от конкретного DbSet<>?

Другие вопросы по тегам