2

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

2 回答 2

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
);
于 2013-01-17T13:58:41.643 回答
0

您可能可以PersistErrors()独立测试。

并且RedirectToAction是一种框架方法。无需测试框架。

仅仅为了代码覆盖而测试catch块的内容似乎有点过分了。不涉及任何逻辑。

您应该测试是否根据需要appraisalOrderService.SubmitApraisalOrder()抛出 a MessageLoneException

记住 80/20 法则。测试覆盖范围的框架效率不高,而且浪费了您作为开发人员恕我直言的宝贵时间。

如果您仍想在此方法中测试 catch 块,您可以伪造您的服务,以便FakeAppraisalOrderService.SubmitApraisalOrder()抛出MessageLoneException.

尽管如此,我还是建议您将时间集中在测试实际逻辑上。100% 的覆盖率是一个理想化的目标,而不是一个规则。

于 2013-01-17T14:19:34.687 回答