如何单元测试此方法的catch块?

时间:2013-01-17 13:53:38

标签: c# asp.net-mvc-3 error-handling nunit rhino-mocks

我正在学习单元测试。如何使用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();
}

2 个答案:

答案 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%的覆盖率是理想化的目标,而不是规则。