#.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
над моделью ответа