-2

I am trying to create a moq for Microsoft.Azure.Documents.Client CreateDocumentQuery

I created an interface with class implementation where I instantiate an object of DocumentClient and make corresponding calls. This is to help moq easy for this.

Here are the code:

public interface IASDocumentClient
{
    IOrderedQueryable<T> CreateDocumentQuery<T>(Uri documentCollectionUri, FeedOptions feedOptions = null);
}

public class ASDocumentClient : IASDocumentClient
{
    DocumentClient client = null;
    public ASDocumentClient(DocumentClient documentClient)
    {
        this.client = documentClient;
    }


    public IOrderedQueryable<Document> CreateDocumentQuery(Uri documentCollectionOrDatabaseUri, FeedOptions feedOptions = null)
    {
        return client.CreateDocumentQuery(documentCollectionOrDatabaseUri, feedOptions);
    }        

    public IQueryable<T> CreateDocumentQuery<T>(Uri documentCollectionOrDatabaseUri, SqlQuerySpec querySpec, FeedOptions feedOptions = null)
    {
        return client.CreateDocumentQuery<T>(documentCollectionOrDatabaseUri, querySpec, feedOptions);
    }
}




   public class DocumentDBRepositoryUnitTest : IDisposable
    {
        IDocumentDBRepository<TestDocumentDBEntity> documentDBRepository;
        List<TestDocumentDBEntity> items = new List<TestDocumentDBEntity>();

        //Pre-test
        public DocumentDBRepositoryUnitTest()
        {
            Mock<IASDocumentClient> documentClient = new Mock<IASDocumentClient>();

            documentClient.Setup(x => x.CreateDocumentQuery<Document>(It.IsAny<Uri>(), It.IsAny<FeedOptions>())).Returns(queryDocuments);
        }


        //Not working now
        [Fact]
        public void GetItemsAsyncTest()
        {
            //Arrange 

            //Act
            var retTask = documentDBRepository.GetItemsAsync(x => true);

            //Assert
            Assert.NotNull(retTask);
            Assert.NotNull(retTask.Result);
        }

        //Post-test
        public void Dispose()
        {
            items = new List<TestDocumentDBEntity>();
        }
    }


public class DocumentDBRepository<T> : IDocumentDBRepository<T> where T : BaseDocumentDBEntity, new()
{
    private string cosmosDbUri;
    private string cosmosDbAuthKey;
    private string databaseId;
    private string collectionId;
    private IASDocumentClient client=null;

    public DocumentDBRepository(IASDocumentClient client, string databaseId, string collectionId)
    {
        this.client = client;
        this.databaseId = databaseId;
        this.collectionId = collectionId;
        if (!string.IsNullOrEmpty(this.databaseId) && !string.IsNullOrEmpty(this.collectionId))
            Initialize();
    }

    public async Task<IEnumerable<T>> GetItemsAsync(Expression<Func<T, bool>> predicate)
    {
      IDocumentQuery<T> query = client.CreateDocumentQuery<T>(
          UriFactory.CreateDocumentCollectionUri(this.databaseId, this.collectionId), new FeedOptions { MaxItemCount = -1 })
        .Where(predicate)
        .AsDocumentQuery();

      List<T> results = new List<T>();
      while (query.HasMoreResults)
      {
        results.AddRange(await query.ExecuteNextAsync<T>());
      }

      return results;
    }
}

When I run the test, its not even reaching out to the mock Setup for CreateDocumentQuery:

documentClient.Setup(x => x.CreateDocumentQuery(It.IsAny(), It.IsAny())).Returns(queryDocuments);

Any idea?

manik
  • 85
  • 1
  • 10
  • Take a look at this answer I gave recently and see if it applies to your problem. https://stackoverflow.com/a/48432085/5233410 – Nkosi Feb 08 '18 at 21:19
  • I tried the approach from your answer. But I am getting this error: Object reference not set to an instance of an object. at System.Linq.Queryable.Where[TSource](IQueryable`1 source, Expression`1 predicate) at DocumentDBRepository`1.d__8.MoveNext() – manik Feb 15 '18 at 19:13

2 Answers2

0

The method you are trying to mock is non-virtual. You can only mock abstract methods on a class or mock an interface of a class.

https://github.com/Moq/moq4/wiki/Quickstart - you can see here that IFoo is an interface and Bar and Baz are concrete classes with abstract methods.

I would suggest you create an abstraction on top of this code. The repository pattern looks to be suitable in this case as you seem to be persisting data. This will allow you to mock the repository you create wherever it will be used e.g. in some kind of service layer. As for testing the actual implementation (the bit where you use the Azure SDK) I would suggest writing an integration test that includes this dependency actually saving the data, either to Storage Emulator or a storage account in Azure.

benjrb
  • 766
  • 1
  • 5
  • 13
  • I have done that, but that seem to be causing some issues. Updated the code above with the example code. – manik Feb 15 '18 at 15:51
0

ASDocumentClient does nothing its a 1: 1 wrapper around client so test has negative value ( 0 value + the cost of having the test). You should also not unit test DocumentDB unless you find a specific issue that's Microsofts job ( that can be picked up with integration tests)

IDocumentDBRepository should be tested and can be via your wrapper interface.

Not having ASDocumentClient / IASDocumentClient wrappers to test Repository is a different but useful question.

user1496062
  • 1,309
  • 1
  • 7
  • 22