我正在学习单元测试。如何使用NUnit和Rhino Mock对此方法进行单元测试?好吧,我已经测试了try
块,并希望测试catch
块代码覆盖率。
[HttpPost]
public ActionResult AppraisalOrderIsAcceptedByEmployee(int appraisalOrderId)
{
try
{
this.appraisalOrderService.SubmitAppraisalOrder(appraisalOrderId);
}
catch (MessageLoneException ex)
{
// Display validation errors
PersistErrors(ex);
// Remains on the same view
return RedirectToAction("VerifyOrderDetails", new { id = appraisalOrderId });
}
return GetLoginRedirectCurrentUser();
}
答案 0 :(得分:6)
假设appraisalOrderService
是一个接口(在正确构建的应用程序中是一个安全的假设),你的控制器作为构造函数注入,你可以使用你最喜欢的模拟框架轻松地模拟它。例如,使用Rhino Mocks,您的测试可能如下所示:
[TestMethod]
public void AppraisalOrderIsAcceptedByEmployee_Should_Redirect_To_VerifyOrderDetails_Action_If_SubmitAppraisalOrder_Throws_A_MessageLoneException()
{
// arrange
var appraisalOrderId = 5;
var orderServiceMock = MockRepository.GenerateMock<IOrderService>();
orderServiceMock
.Expect(x => x.SubmitAppraisalOrder(appraisalOrderId))
.Throw(new MessageLoneException());
var sut = new MyController(orderServiceMock);
// act
var actual = sut.AppraisalOrderIsAcceptedByEmployee(appraisalOrderId);
// assert
Assert.IsInstanceOfType(actual, typeof(RedirectToRouteResult));
Assert.AreEqual("VerifyOrderDetails", result.RouteValues["action"]);
Assert.AreEqual(appraisalOrderId, result.RouteValues["id"]);
}
您尚未展示PersistErrors
方法是什么以及它的行为方式,因此很难说出正确的测试方法。如果此方法正在使用它们,您可能需要模拟其他内容。鉴于您提出的评论,我认为您使用ModelState
以某种方式向AddModelErrorMethod
添加了错误。如果是这种情况,您可以在测试的断言阶段验证它:
Assert.IsFalse(sut.ModelState.IsValid);
如果您知道存储错误的密钥:
Assert.AreEqual(
"some expected message",
sut.ModelState["someKey"].Errors.Single().ErrorMessage
);
答案 1 :(得分:0)
您可以单独测试PersistErrors()
。
RedirectToAction
是一种框架方法。没有必要测试框架。
仅仅为了代码覆盖而测试catch
块的内容似乎有点太过分了。没有涉及逻辑。
您应该测试appraisalOrderService.SubmitApraisalOrder()
是否根据需要抛出MessageLoneException
。
记住80/20规则。测试覆盖框架不是非常有效,浪费了你作为开发人员恕我直言的宝贵时间。
如果您仍想在此方法中测试catch块,则可以伪造您的服务,以便FakeAppraisalOrderService.SubmitApraisalOrder()
抛出MessageLoneException
。
不过,我建议你把时间都集中在测试实际逻辑上。 100%的覆盖率是理想化的目标,而不是规则。