Создание Moq статического метода расширения из LLBLGen - PullRequest
0 голосов
/ 30 апреля 2019

Я пытаюсь использовать Moq для макетирования метода расширения из интерфейса IDataAccessAdapter из LLBLGen.Вот FetchQueryAsync метод расширения.

Это дало мне ошибку, что я не могу издеваться над статическими методами расширения.Однако я не могу изменить код.Поэтому я попытался создать класс-оболочку, но у меня тоже не получилось, потому что я не знаю, как его применить.

В методе Fetch я хочу, чтобы FetchQueryAsync возвращал объект, указанный во время теста, ина самом деле не выполнить запрос.

public class QueryHandler
{
    private IDataAccessAdapterProvider dataAccessAdapterProvider;
    public QueryHandler(IDataAccessAdapterProvider provider)
    {
        this.dataAccessAdapterProvider = provider;
    }

    private async Task<T> Fetch(DynamicQuery<T> query)
    {
        using (IDataAccessAdapter adapter = dataAccessAdapterProvider.Provide()
        {
            result = await adapter.FetchQueryAsync(query)
        }
    }
}

public class DataAccessAdapterProvider : IDataAccessAdapterProvider
{
    public IDataAccessAdapter Provide()
    {
    var adapter = new DataAccessAdapter();
    return adapter;
    }
}

Так что в моем модульном тесте у меня есть это:

List<int> il = new List<int>();

Mock<IDataAccessAdapterProvider> mock = new Mock<IDataAccessAdapterProvider>();

mock.Setup(m => m.Provide()
  .FetchQueryAsync<int>(It.IsAny<DynamicQuery<int>>()))
  .ReturnsAsync(il);

Это не будет работать, однако, потому что он не поддерживается.Поэтому я попытался обернуть метод как таковой.

interface IWrap
{
    Task<List<TElement>> FetchQueryAsync<TElement>(IDataAccessAdapter adapter, DynamicQuery<TElement> query);
}

public class Wrap : IWrap
{
    public async Task<List<TElement>> FetchQueryAsync<TElement>(IDataAccessAdapter adapter, DynamicQuery<TElement> query)
    {
        return await adapter.FetchQueryAsync(query);
    }
}

Как мне применить эту обертку с Moq для насмешки интерфейса?

1 Ответ

2 голосов
/ 30 апреля 2019

Вы начали с метода расширения, а затем создали интерфейс IWrap вместе с реализацией, которая использует метод расширения. Это прекрасно.

Теперь все, что вам нужно, это добавить его в ваш класс, как IDataAccessAdapterProvider уже введено:

public class QueryHandler
{
    private readonly IDataAccessAdapterProvider _dataAccessAdapterProvider;
    private readonly IWrap _wrap; //I'm assuming you'll want a different name.

    public QueryHandler(IDataAccessAdapterProvider provider, IWrap wrap)
    {
        _dataAccessAdapterProvider = provider;
        _wrap = wrap;
    }

(Я применил общее соглашение. Префикс имени поля с подчеркиванием - _wrap - означает, что аргументы поля и конструктора имеют разные имена, поэтому вам не нужно указывать this.wrap. Плюс, когда люди видят это подчеркивание в другом месте, они будут знать, что это поле.)

Теперь вы можете смоделировать интерфейс:

var mock = new Mock<IWrap>();
var returnedFromMock = new List<int> { 1, 2, 3 };
mock.Setup(x => x.FetchQueryAsync<int>(It.IsAny<IDataAccessAdapter>(), It.IsAny<DynamicQuery<int>>()))
    .ReturnsAsync(returnedFromMock);

Вы упомянули, что нет способа изменить код Я не уверен, какую часть вы не можете изменить, но если вы не можете изменить QueryHandler, чтобы заменить его конкретные зависимости, то это может быть просто предостерегающим рассказом о статических зависимостях.

Хотя у вас есть исходный код. Если вы не можете изменить существующий класс, возможно, вы можете просто создать новый из существующего исходного кода. Если кто-то спросит, почему вы продублировали существующий класс, просто скажите (тактично), что вы не хотите дублировать код - вы скорее исправите существующий, чтобы его можно было проверить.

...