2013-01-17 125 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作爲路由值傳回。 –

相關問題