Как я могу создать интерфейс для моего DbContext, если я использую EfCore.BulkExtensions - PullRequest
0 голосов
/ 13 мая 2018

Я работаю над ASP.Net Core 2.0 API, который использует Entity Framework Core 2.0.Я пытаюсь создать модульные тесты, используя XUnit и Moq, но у меня возникла проблема с созданием интерфейса для моего DbContext, чтобы я мог смоделировать его в своих модульных тестах.

В настоящее время мой проект не использует интерфейс для моего контекста.Я внедряю его в свои классы репозитория в качестве его реализации.И в моем Startup.cs я использую services.AddDbContext для его настройки.

Пример типичного конструктора класса репозитория.

    public CompaniesRepository(MyDbContext myDbContext)
    {
        _myDbContext = myDbContext;
    }

Пример Startup.cs

        services.AddDbContext<MyDbContext>(options =>
        {
            options.UseSqlServer(Configuration.GetConnectionString("MyDbConnectionString"),
            sqlOptions =>
            {
                sqlOptions.EnableRetryOnFailure(5,TimeSpan.FromSeconds(30),sqlTransientErrors);
            });
        });

И этот метод работал так же хорошо, как этот.

Однако сейчас я пытаюсь настроить модульные тесты и хочу иметь возможность Mock моего контекста, поэтому мне нужно создать интерфейс дляЭто.

Итак, я добавил в MyDbContext интерфейс IMyDbContext и добавил следующий код в свой Startup.cs, следуя рекомендациям в этом блоге Джерри Пелсера

        services.AddScoped<IMyDbContext>(provider => provider.GetService<MyDbContext>());

Что, похоже, сработало, за исключением одного вопроса.Я также использую NuGet Бориса Джурджевича EFCore.BulkExtensions, и поэтому я получаю ошибку компиляции, исходящую из моих классов репозитория, которая теперь внедряет интерфейс IMyDbContext в свои конструкторы, заявляя, что мой интерфейс не содержит определения для BulkInsert:

Ошибка CS1929 «IMyDbContext» не содержит определения для «BulkInsert» и наилучшей перегрузки метода расширения «DbContextBulkExtensions.BulkInsert (DbContext, IList, BulkConfig, Action)« требуется получатель типа »DbContext '

Я предполагаю, что мне нужно как-то добавить метод расширения BulkInsert в мой интерфейс IMyDyBontext, но я не уверен, как это сделать правильно.Если я просто пытаюсь добавить метод в свой интерфейс, то получаю сообщение об ошибке, утверждая, что он не реализован в моем классе MyDbContext, конечно.

Как ссылаться на метод расширения BulkInsert в моем классе MyDbContext?

Ответы [ 2 ]

0 голосов
/ 18 марта 2019

Недавно я столкнулся с этой проблемой при подготовке к макету моего DbContext для модульного тестирования при использовании пакета EF Core BulkExtensions. Ответ, помеченный как правильный ответ, ПОЧТИ правильный (хотя они и сказали, что не проверяли свой код).

При реализации этого внутри класса DbContext описанным выше способом вы получите исключение StackOverflowException при вызове метода BulkInsert.

Итак, я начал отладку и решил установить точку останова на метод внутри класса DbContext, чтобы увидеть, что происходит. Это привело меня к пониманию причины возникновения исключения StackOverflowException: этот метод вызывал сам себя вместо метода базового класса DbContext из-за области действия ключевого слова this.

Решение было довольно простым, решенным следующим изменением в реализации метода BulkInsert внутри реализации MyDbContext:

public async Task BulkInsertAsync<T>(IList<T> entities, BulkConfig bulkConfig = null, Action<decimal> progress = null) where T : class
{
    await ((DbContext)this).BulkInsertAsync<T>(entities, bulkConfig, progress);
}

Кроме того, добавьте следующую строку в интерфейс IMyDbContext:

Task BulkInsertAsync<T>(IList<T> entities, BulkConfig bulkConfig = null, Action<decimal> progress = null) where T : class;

Это гарантировало, что область видимости «this» была приведена к базовому типу класса DbContext, а не к типу моей собственной реализации DbContext. Поэтому вместо вызова самого себя он вызывал метод расширения с использованием базового класса DbContext.

Используя это решение, вы теперь сможете успешно использовать метод расширения в своем коде, как показано ниже:

await _context.BulkInsertAsync<User>(users);

Надеюсь, кто-нибудь найдет это полезным. Это было не так уж плохо, чтобы разобраться с помощью отладки, и я гарантировал, что все мои методы будут легко проверяемыми при использовании пакета BulkExtensions!

0 голосов
/ 13 мая 2018

BulkInsert - это метод расширения. Вы не можете издеваться над статическим методом легко .

Вместо этого вы можете реализовать его внутри MyDbContext класса. Затем вы могли бы высмеять IMyDbContext для модульного тестирования. Примечание: я не проверял.

public interface IMyDbContext
{
    void BulkInsert<T>(IList<T> entities, BulkConfig bulkConfig = null,
        Action<decimal> progress = null) where T : class;

}

public class MyDbContext : DbContext, IMyDbContext
{
    public void BulkInsert<T>(IList<T> entities, BulkConfig bulkConfig = null,
        Action<decimal> progress = null) where T : class
    {
        this.BulkInsertOrUpdate(entities, bulkConfig, progress);
    }
}
...