简体   繁体   中英

Moq, test method return error - System.ArgumentNullException: Value cannot be null. (Parameter 'source')

I have following service:

The DocumentTypeService class

public partial class DocumentTypeService : IDocumentTypeService
{
    private readonly IRepository<DocumentType> _documentTypeRepository;
    private readonly IMediator _mediator;

    public DocumentTypeService(IRepository<DocumentType> documentTypeRepository, IMediator mediator)
    {
        _documentTypeRepository = documentTypeRepository;
        _mediator = mediator;
    }

    public virtual async Task<IList<DocumentType>> GetAll()
    {
        var query = from t in _documentTypeRepository.Table
            orderby t.DisplayOrder
            select t;
        return await query.ToListAsync();
    }
}

The test agains GetAll() method

[TestClass()]
public class DocumentTypeServiceTests
{
    private Mock<IRepository<DocumentType>> _documentTypeRepositoryMock;
    private DocumentTypeService _documentTypeService;
    private Mock<IMediator> _mediatorMock;

    [TestInitialize()]
    public void Init()
    {
        _mediatorMock = new Mock<IMediator>();
        _documentTypeRepositoryMock = new Mock<IRepository<DocumentType>>();
        _documentTypeService = new DocumentTypeService(_documentTypeRepositoryMock.Object, _mediatorMock.Object);
    }


    [TestMethod()]
    public async Task GetAllDocumentTypes()
    {
        await _documentTypeService.GetAll();
        _documentTypeRepositoryMock.Verify(c => c.Table, Times.Once);
    }
}

The error that the GetAllDocumentTypes() method returns

Test method Grand.Services.Tests.Documents.DocumentTypeServiceTests.GetAllDocumentTypes threw exception:
System.ArgumentNullException: Value cannot be null. (Parameter 'source')
Stack Trace:
Queryable.OrderBy[TSource,TKey](IQueryable'1 source, Expression'1 keySelector)
MongoQueryable.OrderBy[TSource,TKey](IMongoQueryable'1 source, Expression'1 keySelector)

UPDATE:

/// <summary>
/// MongoDB repository
/// </summary>
public partial class Repository<T> : IRepository<T> where T : BaseEntity
{
    /// <summary>
    /// Gets a table
    /// </summary>
    public virtual IMongoQueryable<T> Table
    {
        get { return _collection.AsQueryable(); }
    }
}

You should mock the following method call:

_documentTypeRepository.Table

Specifically, you need something like this:

_documentTypeRepositoryMock = new Mock<IRepository<DocumentType>>();
var mongoQueryableMock = new Mock<IMongoQueryable<DocumentType>>();
_documentTypeRepositoryMock.Setup(x=>x.Table).Returns(mongoQueryableMock);

Doing so, when _documentTypeRepository.Table is called would return an empty list of DocumentType and no need for OrderBy to be called. The default behavior is, since you don't mock this call, _documentTypeRepository.Table returns null. Hence the null pointer exception later on.

In order to understand the latter argument, you should be aware of how the query syntax works compile-wise. Query syntax is just syntactic sugar. When you code is compiled, it is replaced first by the equivalent ("LINQ") method calls, and the the corresponding IL code is generated. So your query:

from t in _documentTypeRepository.Table
orderby t.DisplayOrder
select t;

would be first transformed in a query like the following one:

_documentTypeRepository.Table
                       .OrderBy(x=>x)
                       .Select(x=>x)

and later on the corresponding IL code would be generated based on the latter query.

So, if _documentTypeRepository.Table returns null, then calling OrderBy would throw a null pointer exception.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM