我最近搬到了我公司的一个新项目。我的任务是为REST API的一个控制器编写单元测试。控制器实现System.Web.Http.ApiController接口。我正在使用Moq,这是我第一次使用这个很酷的小库。我的问题是,当我打电话
IHttpActionResult result = Ok();
在控制器中,对Ok()的调用返回null。这只发生在我从单元测试中调用此方法时。如果我直接使用Swagger调用我的方法,它会按预期工作。
我在想,我用来设置控制器参数/控制器本身的Moq语句可能会以某种方式搞乱控制器的实例化并使继承的接口方法无法访问?这是我用来设置单元测试的代码:
//Mock ICrmService to return an Id for a created company
var crmCacheService = new Mock<ICrmCacheService>();
var crmService = new Mock<ICrmService>();
crmCacheService.Setup(x => x.CreateSubscription(It.IsAny<CreateSubscriptionModel>())).Returns(true);
crmService.Setup(x => x.CreateSubscription(It.IsAny<CreateSubscriptionModel>())).Returns(ReturnedSubscriptionId);
var controller = new Mock<SubscriptionController>(crmService.Object, crmCacheService.Object);
IHttpActionResult actionResult = controller.Object.CreateSubscriptions(Guid.NewGuid().ToString(), 1);
有没有人知道为什么这会使Ok()的调用返回null?我如何设置它以便调用Ok()将返回System.Web.Http.Results.OkResult的正常结果?
答案 0 :(得分:1)
在这种情况下,您的控制器可能是您正在测试的主题,在这种情况下,您根本不想真正模拟它,而是使用真实实例(使用模拟依赖项):
var controller = new SubscriptionController(crmService.Object, crmCacheService.Object);
当你正在嘲笑它时,由于Ok()方法在ApiController中是虚拟的,Moq将能够覆盖它并将这样做。由于默认的模拟行为是覆盖所有内容以返回默认值(MockBehavior.Loose),因此您将获得null返回值。
如果你确实想要模拟它并从Ok()返回一个值,我再也不认为你做了,你可以使用安装程序将它传递给真正的方法(在其他许多方法中)事情,比如指定你想要的返回值):
controller.Setup(x => x.Ok()).CallBase();
答案 1 :(得分:1)
Mock类有一个名为CallBase
的属性来控制覆盖所有虚拟方法的默认行为。你可以轻松地说:
controller.CallBase = true;