Reputation: 415
I am trying to mock the result of a repository method which will return me a list of class objects. Am having a check if the result contains data then the API will return the status code depending on the check. Am able to mock the result but it throwing null reference exception while it checking the results contains data. Here is the code for controller and test case.
public IActionResult Get([FromQuery] FilterRequst request)
{
IEnumerable<Student> result = _repository.GetAll(Mapper.Map<StudentFilter>(request));
if (result != null && result.Count() > 0)//here throwing null reference exception
{
List<StudentModel> model = Fill(result.ToList());
var response = new StudentListModel()
{
TotalRecords = model.Count,
Items = model
};
return new ObjectResult("OK")
{
StatusCode = (int?)HttpStatusCode.OK,
Value = response
};
}
return new ObjectResult("No Content")
{
StatusCode = (int?)HttpStatusCode.NoContent,
Value = "No Content"
};
}
Testcase:
public void StudentGetAllTestReturnsStudents()
{
var fakeStudents = new Mock<IEnumerable<Student>>();
_mockRepository.Setup(x => x.GetAll(It.IsAny<Filter>())).Returns(fakeStudent.Object);
_studentController = new StudentsController(_mockRepository.Object);
Mapper.Initialize(cfg =>
{
cfg.CreateMap<FilterModel, Filter>();
});
// Act
var actionResult = _studentController.Get(It.IsAny<FilterModel>());
var result = actionResult as ObjectResult;
var model = result.Value as StudentListModel;
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(StatusCodes.Status200OK, result.StatusCode);
Assert.IsNotNull(model);
}
How can I mock the IEnumerable<Student>
which can be checked for not null
and Count
?
Upvotes: 0
Views: 1192
Reputation: 4057
There are two reasons why your code is not working.
IEnumerable<>
but not setting it up so that its methods and properties return values. You are calling .Count()
but not specifying what the mocked object should do when that method is called.IEnumerable<>
to return fake values, you cannot directly mock extension methods such as .Count()
. See this answer.You do not need to mock IEnumerable
. You only need to mock your classes, and only when you want to override their default behavior.
Upvotes: 1
Reputation: 247531
The arranged setup and the invocation of the method under test was not done correctly
public void StudentGetAllTestReturnsStudents() {
//Arrange
var fakeStudents = new List<Student>() { //used actual list instead of mock
new Student() { }
};
_mockRepository
.Setup(_ => _.GetAll(It.IsAny<StudentFilter>()))
.Returns(fakeStudents);
_studentController = new StudentsController(_mockRepository.Object);
Mapper.Initialize(cfg => {
cfg.CreateMap<FilterRequst, StudentFilter>();
});
// Act
var actionResult = _studentController.Get(new FilterRequst());//use actual model
var result = actionResult as ObjectResult;
var model = result.Value as StudentListModel;
// Assert
Assert.IsNotNull(result);
Assert.AreEqual(StatusCodes.Status200OK, result.StatusCode);
Assert.IsNotNull(model);
}
Just because you can mock objects does not mean that you always should. If you can use an actual object without causing negative side effects then go ahead. You mock the things you want to change the behavior of, like dependencies.
Student
and other models should be safe to use their instances provided they have no unwanted behavior.
Upvotes: 0