Как издеваться над SearchClient.SearchAsync с помощью Azure Cognitive Search SDK?

#.net #.net-core #mocking #azure-cognitive-search #automoq

#.net #.net-ядро #издевательство #azure-cognitive-search #automoq

Вопрос:

Я пытаюсь выполнить модульное тестирование кода, который использует SearchClient.SearchAsync() метод. Я использую автофиксацию.Пакет AutoMoq nuget.

Вот что я попробовал:

 mockSearchClient.Setup(msc => msc.SearchAsync<MyModel>(
        It.IsAny<string>(),
        It.IsAny<SearchOptions>(),
        It.IsAny<CancellationToken>()
    )).Returns(Task.FromResult(<<PROBLEM HERE>>));
  

Проблема заключается в .Returns(Task.FromResult(<<PROBLEM HERE>>)) части параметров. Он ожидает конкретный объект, который возвращается из .SearchAsync() метода. Согласно документам и автозаполнению, метод возвращает Azure.Response абстрактный класс. Итак, я не могу создать его заново. На самом деле метод возвращает класс-потомок Azure.ValueResponse , который не является абстрактным, а является внутренним для Azure SDK, поэтому его также невозможно создать заново.

Итак, как можно издеваться над SearchClient.SearchAsync?

Постскриптум С использованием Azure.Поиск.Документы, версия 11.1.1.0

Комментарии:

1. И вы не можете создать свою собственную подделку, производную от абстрактного класса response?

2. @BertrandLeRoy Фреймворки-макеты обычно требуют, чтобы вы предоставили экземпляр. Итак, я попытался создать свой собственный класс, унаследованный от Azure.Response ( class foo: Azure.Response {} ) , но это тоже не сработало. Если у вас есть другой способ сделать это, я бы с удовольствием попробовал.

Ответ №1:

См . https://github.com/Azure/azure-sdk-for-net/blob/master/sdk/core/Azure.Core/README.md#mocking для получения информации. В принципе, вы можете использовать Response.FromValue вместе с SearchModelFactory (шаблоном, которому мы следуем со всеми нашими Azure. * клиентскими SDK для моделей, которые нельзя полностью воспроизвести с помощью конструктора и / или настраиваемых свойств), чтобы создать макет, подобный этому (используя Moq, поскольку я не знаком с AutoMoq, но должен быть похожим):

 var responseMock = new Mock<Response>();

var clientMock = new Mock<SearchClient>(() => new SearchClient(new Uri("https://localhost"), "index", new AzureKeyCredential("key")));
clientMock.SetupGet(x => x.IndexName).Returns("index");
clientMock.Setup(x => x.SearchAsync<Hotel>(
        It.IsAny<string>(),
        It.IsAny<SearchOptions>(),
        It.IsAny<CancellationToken>()
    ))
    .Returns(
        Task.FromResult(
            Response.FromValue(
                SearchModelFactory.SearchResults(new[]
                    {
                        SearchModelFactory.SearchResult(new Hotel("1", "One"), 0.9, null),
                        SearchModelFactory.SearchResult(new Hotel("2", "Two"), 0.8, null),
                    },
                    100,
                    null,
                    null,
                    responseMock.Object),
                responseMock.Object)));

var results = await clientMock.Object.SearchAsync<Hotel>("test").ConfigureAwait(false);
var hotels = results.Value;

Assert.Equal(2, hotels.GetResults().Count());
Assert.Equal(100, hotels.TotalCount);
  

Комментарии:

1. Просто хотел добавить, что форма делегирования, используемая в new Mock<SearchClient> , необходима только из-за ошибки, которая с тех пор была исправлена: github.com/Azure/azure-sdk-for-net/pull/15671 . Обычно вы можете просто использовать конструкцию, которая принимает параметры, передаваемые клиенту, например SearchClient .

2. Спасибо @heath, это помогло мне найти TableModelFactory способ издеваться TableServiceClient над моделью ответа