I have a method in a repository that receives an Expression
as a parameter and the result of the method are supposed to filter by that expression. The thing is that when I try to test this method, it doesn't give me the result filtered:
Service method I'm testing
public async Task<Response<IEnumerable<AirlineDto>>> GetAllAsync()
{
try
{
var airlines = await _airlineRepository.GetAsync(x => x.Status); // call to the real repo
... // some logic
}
... // exception handling
}
Method Setup, MockAirlineRepository
is a mock of AirlineRepository
public MockAirlineRepository MockGetAll()
{
Setup(x => x.GetAsync(It.IsAny<Expression<Func<Airline, bool>>>()))
.ReturnsAsync(GetTestAirlines);
return this;
}
private static IEnumerable<Airline> GetTestAirlines()
{
var airlines = new List<Airline>
{
new()
{
Id = Guid.NewGuid(),
Name = "Test One",
Status = true
},
new()
{
Id = Guid.NewGuid(),
Name = "Test Two",
Status = true
},
new()
{
Id = Guid.NewGuid(),
Name = "Test Three",
Status = false // notice that this Airline Status is false, so,
// the count of the retrieved values should be 2
}
};
return airlines;
}
Test
[Fact]
public void AirlineService_GetAll_ReturnsAirlines()
{
//Arrange
var mockAirlineRepo = new MockAirlineRepository().MockGetAll();
var airlineService = new AirlineService(mockAirlineRepo.Object, _airlineMapper);
//Act
var result = airlineService.GetAllAsync().Result.Data;
//Assert
var airlineDtoList = result.ToList();
Assert.NotEmpty(airlineDtoList);
Assert.Equal(2, airlineDtoList.Count); // assert fails, because airlineDtoList.Count is 3
mockAirlineRepo.VerifyGetAllAirlines(Times.Once());
}
CodePudding user response:
Let's start with the basics:
- Dummy: simple code that returns bogus data
- Fake: a working alternative which can take shortcuts
- Stub: custom logic with predefined data
- Mock: custom logic with expectations (interactive stub)
- Shim: custom logic at run-time (replace static with a delegate)
- Spy: interceptors to record calls
So, your mock is an interactive stub which means it can return different outputs based on the received input. In your Setup
call you have made the following statement: whatever I receive as a filter expression I should always return with the entire list
If you want to apply the filter then change your setup
.Setup(x => x.GetAsync(It.IsAny<Expression<Func<Airline, bool>>>()))
.ReturnsAsync(filter => GetTestAirlines.Where(filter));
Now if you assert on airlineDtoList.Count
then it will return 2. But in this case you are not testing the GetAllAsync
function rather than your mock.
So, I would rather spend more time testing the // some logic
You can also take advantage of async
-await
in your test
[Fact]
public Task AirlineService_GetAll_ReturnsAirlines()
{
//Arrange
var mockAirlineRepo = new MockAirlineRepository().MockGetAll();
var airlineService = new AirlineService(mockAirlineRepo.Object, _airlineMapper);
//Act
var response = await airlineService.GetAllAsync();
var result = response.Data;
//Assert
...
}