2013-01-17 69 views
2

我正在学习单元测试。如何使用NUnit和Rhino Mock对此方法进行单元测试?那么我已经测试try区块,并且想要测试catch区块的代码覆盖范围。如何对此方法的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(); 
} 

回答

6

假设appraisalOrderService是一个接口(其中一个正确设计的应用程序是一个安全的假设使)您的控制器采用构造函数注入你可以很容易地与您喜爱的模拟框架嘲笑它。例如与犀牛嘲笑你的测试可能是这样的:

[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方法是什么以及它如何工作,所以很难讲,以测试它的正确方法。如果此方法正在使用它们,您可能需要嘲笑其他东西。考虑到你已经把它放在上面的评论,我想你不知何故使用AddModelErrorMethod将错误添加到ModelState。如果是这样的话,你可以验证它在测试的断言阶段:

Assert.IsFalse(sut.ModelState.IsValid); 

,如果你知道下储存了错误的关键在于:

Assert.AreEqual(
    "some expected message", 
    sut.ModelState["someKey"].Errors.Single().ErrorMessage 
); 
+0

嘿谢谢你。我有一个问题。当我在aather类中编写测试时,我应该使用反射来访问测试用例的私有方法吗? –

+1

不,你应该**不**使用任何反射。你应该**不**单元测试私人方法。这是实施细节。您应该测试调用这些私有方法的公共方法。 –

0

你或许可以单独测试PersistErrors()

RedirectToAction是一个框架方法。没有必要测试框架。

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

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

请记住80/20规则。测试框架的覆盖率不是非常有效,而且浪费了开发人员恕我直言的宝贵时间。

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

不过,我建议把时间集中在测试实际逻辑上。 100%的覆盖率是一个理想化的目标,而不是一个规则。

+1

尽管'RedirectToAction'是一个框架方法,它正在被传递的值应该被断言。 –

+0

@TrevorPilley你的断言究竟是什么?那'appraisalOrderId'仍然是一样的?我没有看到任何代码操纵它。 –

+1

'var result =(RedirectToRouteResult)controller.AppraisalOrderIsAcceptedByEmployee(appraisalOrderId); Assert.AreEqual(appraisalOrderId,result.RouteValues [“id”]); Assert.AreEqual(“VerifyOrderDetails”,result.RouteValues [“action”]);'您应该断言您正在重定向到正确的操作并将appraisalOrderId作为路由值传回。 –

相关问题