Search code examples
c#unit-testingasp.net-core-webapinunitweb-api-testing

Get function for searching is not giving the search result but returning all the elements while unit testing


I have a function called GetAuthors which takes an expression for checking if given string is in authors names. I have problems while unit testing. The function supposed to find names that contains the given string but I realized it always returns everything in the list. I tested with G letter it supposed to fail but it passes. I have only found examples with no parameters for get functions unit testing. I am new to unit testing in web api. I share the code below.

Test function:

[Test]
    public async Task AuthorHandler_GetAuthors_ReturnsAuthors()
    {
        var handler = new GetAuthorsHandler(_authorRepositoryMock.Object, _mapper);
        var authors = new List<Author> { 
            new Author{Id = 2, Name = "Orhan", Surname = "Pamuk"},
            new Author{Id = 3, Name = "Patti", Surname = "Smith"},
            new Author{Id = 1, Name = "J.R.R.", Surname = "Tolkien"}

        };
        
        string str = "G";
        str=str.Trim().ToUpper();
        _authorRepositoryMock.Setup(r => r.GetAuthors(It.IsAny<Expression<Func<Author, bool>>>()))
            .ReturnsAsync(authors);

        //Act
        var result = await handler.Handle(new GetAuthorsQuery(str), CancellationToken.None);
        
        //Assert
        Assert.AreNotEqual(0, result.Count());

    }

GetAuthors function in repository:

public async Task<IEnumerable<Author>> GetAuthors(Expression<Func<Author, bool>> pred = null)
    {
        if (pred == null) return await _context.Authors.Include(a => a.Book).ToListAsync();
        else return await _context.Authors.Where(pred).Include(b => b.Book).ToListAsync();
    }

Handler:

   public async Task<IEnumerable<AuthorDto>> Handle(GetAuthorsQuery request, CancellationToken cancellationToken)
    {
        IEnumerable<Author> authors;
        if (request.Str != null)
        {
            request.Str = request.Str.Trim().ToUpper();
            authors = await _authorRepository.GetAuthors(x => x.Name.Trim().ToUpper().Contains(request.Str));
        }
        else { authors = await _authorRepository.GetAuthors(null); }
        
        if (authors == null) return null;
        return _mapper.Map<List<AuthorDto>>(authors);
    }

Solution

  •     _authorRepositoryMock.Setup(r => r.GetAuthors(It.IsAny<Expression<Func<Author, bool>>>()))
            .ReturnsAsync(authors);
    

    This line means, that whenever you ask for _authorRepository.GetAuthors(predicate);, you will always get the same result -> authors. You are not testing filtering, because you've mocked it entirely.

    You can mock the repository to use the predicate on authors list, like so:

    _authorRepositoryMock.Setup(r => r.GetAuthors(It.IsAny<Expression<Func<Author, bool>>>()))
        .ReturnsAsync((Expression<Func<Author, bool>> predicate) => authors.Where(predicate));
    

    Mocks can not only return hardcoded data, but can also perform some logic, or return delegate functions.