Ways to test SearchResults<T> Class in Azure.Search.Documents v11.2.0

Viewed 564

I'm trying to find out a way to unit test the search results from the SearchResults<T> Class with different parameters.

Compared to DocumentSearchResult<T> Class which was in the previous package Microsoft.Azure.Search.Data v10.1.0, SearchResults<T> Class does not have any constructors, just properties and methods.

DocumentSearchResult<T> Class https://docs.microsoft.com/en-us/dotnet/api/microsoft.azure.search.models.documentsearchresult-1?view=azure-dotnet

SearchResults<T> Class https://docs.microsoft.com/en-us/dotnet/api/azure.search.documents.models.searchresults-1?view=azure-dotnet

I couldn't seem to find any documentation on that online as it is relatively new, but any ideas or suggestions are most welcome.

Thank you.

2 Answers

All our Azure SDKs for .NET matching package names Azure.* like Azure.Search.Documents are mockable using the same principles as shown here. For pure response objects like SearchResults<T>, we create model factories so that you can create them for testing. In general, there is no other intended purpose for creating them apart from testing.

Using Moq, for example:

// Arrange
var mockResponse = new Mock<Response>();
var mockResults = SearchModelFactory.SearchResults<Model>(new[]
{
  SearchModelFactory.SearchResult<Model>(new Model { Name = "a" }, 1.0),
  SearchModelFactory.SearchResult<Model>(new Model { Name = "b" }, 0.9),
}, 2, rawResponse: response.Object);

var mockClient = new Mock<SearchClient>();
mockClient.Setup(m => m.Search<Model>(It.IsAny<string>(), It.IsAny<SearchOptions>(), default))
  .Returns(Response.FromValue(mockResults, mockResponse.Object));

// Act
var response = mockClient.Object.Search<Model>("anything");

// Assert
Assert.AreEqual(2, response.Value.TotalCount);

See more mocking samples for other ideas.

The SearchModelFactory is the class that will help you to create the models for SearchResults.

This reading can also be helpful for another kind of tests: https://devblogs.microsoft.com/azure-sdk/unit-testing-and-mocking/

Just in case someone else is looking for a version using NSubstitute, here is mine:

public async Task TheTest()
{
    // Arrange
    var searchResultValues = new List<SearchResult<MyModel>>
    {
        SearchModelFactory.SearchResult<MyModel>(new MyModel{Id = 1}, score:0.9, highlights:null),
        SearchModelFactory.SearchResult<MyModel>(new MyModel{Id = 2}, score:0.8, highlights:null),
    };
    var searchResults = SearchModelFactory.SearchResults<MyModel>(searchResultValues, totalCount: 2, facets: null, coverage: 1.3, rawResponse: Substitute.For<Response>());
    var response = Response.FromValue(searchResults, Substitute.For<Response>());

    var searchClient = Substitute.For<SearchClient>();
    searchClient.SearchAsync<MyModel>(Arg.Any<string>(), Arg.Any<SearchOptions>()).Returns(Task.FromResult(response));

    var sut = new ClassThatUsesTheSearchClient(searchClient);

    // Act
    var result = await sut.MethodToSearch();
    // or directly 
    var directResult = await searchClient.SearchAsync<MyModel>("text");

    // Assert
    Assert.AreEqual(2, directResult.Value.TotalCount);
    ...
}
Related