用Moq框架模拟课堂



我正在尝试模拟一个存储库方法的结果,该方法将返回一个类对象列表。如果检查结果包含数据,则API将根据检查返回状态代码。我可以模拟结果,但它在检查结果是否包含数据时抛出了null引用异常。这是控制器和测试用例的代码。

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"
};
}

测试用例:

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

我如何模拟可以检查不是nullCountIEnumerable<Student>

您的代码无法工作有两个原因。

  1. 您正在模拟IEnumerable<>,但没有设置它以使其方法和属性返回值。您正在调用.Count(),但没有指定在调用该方法时模拟对象应该做什么
  2. 即使将IEnumerable<>设置为返回假值,也不能直接模拟.Count()等扩展方法。看看这个答案

您不需要模拟IEnumerable。您只需要模拟您的类,并且仅当您想要覆盖它们的默认行为时。

测试中方法的安排设置和调用未正确完成

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

仅仅因为你可以模拟对象并不意味着你总是应该这样做。如果你能在不产生负面副作用的情况下使用实际物体,那就继续吧。你嘲笑那些你想改变行为的东西,比如依赖关系。

Student和其他模型应该可以安全地使用它们的实例,前提是它们没有不需要的行为。

最新更新