ApiController.Ok() returns 单元测试中为空
ApiController.Ok() returns null in unit tests
我最近搬到了我公司的一个新项目。我的任务是为我们的一个控制器编写 REST API 的单元测试。控制器实现了 System.Web.Http.ApiController interface. I am using Moq,这是我第一次使用这个很酷的小库。我的问题是当我打电话给
IHttpActionResult result = Ok();
在控制器中,对 Ok() 的调用 returns 为空。这仅在我从单元测试中调用此方法时发生。如果我直接使用 Swagger 调用我的方法,它会按预期工作。
我在想,我用来设置控制器的起订量语句 arguments/controller 本身可能会以某种方式干扰控制器的实例化,并使继承的接口方法无法访问?这是我用来设置单元测试的代码:
//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() return 的调用为空?我如何设置它以便调用 Ok() 将 return 成为 System.Web.Http.Results.OkResult?
的正常结果
假设您的控制器是您在这种情况下的测试对象,在这种情况下您根本不想模拟它,而是使用真实实例(具有模拟依赖项):
var controller = new SubscriptionController(crmService.Object, crmCacheService.Object);
由于您目前正在模拟它,并且由于 Ok() 方法在 ApiController 中是虚拟的,Moq 将能够覆盖它并且会这样做。由于默认的模拟行为是将所有内容覆盖为 return 默认值 (MockBehavior.Loose),您将得到一个空的 return 值。
如果您真的想模拟它并且 return 来自 Ok() 的值,同样,我不认为您这样做,您可以使用 Setup 将其传递给真正的方法(除许多其他事项外,例如指定要获得的 return 值):
controller.Setup(x => x.Ok()).CallBase();
Mock class 有一个名为 CallBase
的 属性 来控制是否覆盖所有虚拟方法的默认行为。你可以轻松地说:
controller.CallBase = true;
此答案的更多详细信息:
我最近搬到了我公司的一个新项目。我的任务是为我们的一个控制器编写 REST API 的单元测试。控制器实现了 System.Web.Http.ApiController interface. I am using Moq,这是我第一次使用这个很酷的小库。我的问题是当我打电话给
IHttpActionResult result = Ok();
在控制器中,对 Ok() 的调用 returns 为空。这仅在我从单元测试中调用此方法时发生。如果我直接使用 Swagger 调用我的方法,它会按预期工作。
我在想,我用来设置控制器的起订量语句 arguments/controller 本身可能会以某种方式干扰控制器的实例化,并使继承的接口方法无法访问?这是我用来设置单元测试的代码:
//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() return 的调用为空?我如何设置它以便调用 Ok() 将 return 成为 System.Web.Http.Results.OkResult?
的正常结果假设您的控制器是您在这种情况下的测试对象,在这种情况下您根本不想模拟它,而是使用真实实例(具有模拟依赖项):
var controller = new SubscriptionController(crmService.Object, crmCacheService.Object);
由于您目前正在模拟它,并且由于 Ok() 方法在 ApiController 中是虚拟的,Moq 将能够覆盖它并且会这样做。由于默认的模拟行为是将所有内容覆盖为 return 默认值 (MockBehavior.Loose),您将得到一个空的 return 值。
如果您真的想模拟它并且 return 来自 Ok() 的值,同样,我不认为您这样做,您可以使用 Setup 将其传递给真正的方法(除许多其他事项外,例如指定要获得的 return 值):
controller.Setup(x => x.Ok()).CallBase();
Mock class 有一个名为 CallBase
的 属性 来控制是否覆盖所有虚拟方法的默认行为。你可以轻松地说:
controller.CallBase = true;
此答案的更多详细信息: