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);
}
_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.