I am writing a simple xunit test case for a service class.
I have mocked _userAPIRepository
but it returns null value. It should return teacherDetails
.
Below is the service class method and xunit test case method.
Service method
public async Task<List<TeacherDto>> GetTeacherDetails(Teacher teacher)
{
List<TeacherDto> teacherDetails = new List<TeacherDto>();
UserByUsername userByUsername = new UserByUsername
{
Username = teacher.Name,
Id = teacher.Id
};
teacherDetails = await _userServiceAPI.GetUserIdsByName(userByUsername);
return teacherDetails;
}
xunit test case
[Fact()]
public async Task GetUserDetails()
{
//Arrange
List<TeacherDto> teacherDetails = ServiceDataSource.teacherDetails();
Teacher teacher = ServiceDataSource.teacher();
UserByUsername userByUsername = new UserByUsername
{
Username = teacher.Name,
Id = teacher.Id
};
_userAPIRepository.Setup(x => x.GetUserIdsByName(userByUsername)).Returns(Task.FromResult(teacherDetails);
var result = await _userServiceAPI.GetTeacherDetails(teacher);
//Assert
Assert.True(result.Count > 0);
}
CodePudding user response:
The mock returns null by default when the arguments setup do not match what was passed in when exercising the test. In the presented case, an actual instance/reference was used which does not match the instance created within the subject under test.
Use argument matcher to get the desired behavior from mock since the argument is initialized within the subject under test.
[Fact()]
public async Task GetUserDetails() {
//Arrange
List<TeacherDto> teacherDetails = ServiceDataSource.teacherDetails();
Teacher teacher = ServiceDataSource.teacher();
_userAPIRepository
.Setup(x => x.GetUserIdsByName(It.Is<UserByUsername>(u =>
u.Username == teacher.Name && u.Id == teacher.Id)))
.ReturnsAsync(teacherDetails);
//Act
var result = await _userServiceAPI.GetTeacherDetails(teacher);
//Assert
Assert.True(result.Count > 0);
}
Note the use of It.Is<>
to add an argument matcher with a specific filter/predicate.
If there is no need to actually match the members and just accept any UserByUsername
, then It.IsAny<>
could be used instead
For example
[Fact()]
public async Task GetUserDetails() {
//Arrange
List<TeacherDto> teacherDetails = ServiceDataSource.teacherDetails();
Teacher teacher = ServiceDataSource.teacher();
_userAPIRepository
.Setup(x => x.GetUserIdsByName(It.IsAny<UserByUsername>()))
.ReturnsAsync(teacherDetails);
//Act
var result = await _userServiceAPI.GetTeacherDetails(teacher);
//Assert
Assert.True(result.Count > 0);
}
Reference Moq Quickstart to get a better understanding of how to use that library