程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 單元測試的一些常見問題總結

單元測試的一些常見問題總結

編輯:C#入門知識

此文收集一些平時使用單元測試碰到的問題和解決辦法,供大家參考。

如何檢查返回的集合類是否符合期望?

Microsoft UnitTestFramework 如果需要元素的順序一致,可以使用CollectionAssert.AreEqual;如果不需要考慮順序,可以使用CollectionAssert.AreEquivalent。(有的地方說MSTest的Assert.AreEqual支持集合類型比較,我測試過,忽悠人的) nUnit 同上 xUnit xUnit的Assert.Equal(c1, c2)可以支持集合類型比較,c1和c2的元素順序必須一致

Microsoft UnitTestFramework / nUnit / xUnit 比較,使用哪個框架更合適?

Microsoft UnitTestFramework和nUnit的用法非常類似,而xUnit由於吸取了nUnit的設計上的經驗,用法更加簡潔。下面是周公寫的兩篇文章,nUnit和xUnit介紹的非常詳細,大家可以閱讀一下:

  • 在.NET開發中的單元測試工具之(1)——NUnit
  • 在.NET開發中的單元測試工具之(2)——xUnit.Net

什麼是Mock?

單元測試的目標是一次只驗證一個方法,小步的前進,細粒度的測試,但是假如某個方法依賴於其他一些難以操控的東東,比如說網絡連接、數據庫連接、系統時間、或者是Servlet容器,那麼我們該怎麼辦呢?要是你的測試依賴於系統的其他部分,甚至是系統的多個其他部分呢?在這種情況下,倘若不小心,你最終可能會發現自己幾乎初始化了系統的每個組件,而這只是為了給一個測試創造足夠的運行環境讓它們可以運行起來。忙乎了大半天,看上去我們好像有點違背了測試的初衷了。這樣不僅僅消耗時間,還給測試過程引入了大量的耦合因素,比如說,可能有人興致沖沖地改變了一個接口或者數據庫的一張表,突然,你那卑微的單元測試的神秘的掛掉了。在這種情況發生幾次之後,即使是最有耐心的開發者也會洩氣,甚至最終放棄所有的測試,那樣的話後果就不能想像了。

再讓我們看一個更加具體的情況:在實際的面向對象軟件設計中,我們經常會碰到這樣的情況,我們在對現實對象進行構建之後,對象之間是通過一系列的接口來實現。這在面向對象設計裡是最自然不過的事情了,但是隨著軟件測試需求的發展,這會產生一些小問題。舉個例子,用戶A現在拿到一個用戶B提供的接口,他根據這個接口實現了自己的需求,但是用戶A編譯自己的代碼後,想簡單模擬測試一下,怎麼辦呢?這點也是很現實的一個問題。我們是否可以針對這個接口來簡單實現一個代理類,來測試模擬,期望代碼生成自己的結果呢?幸運的是,有一種測試模式可以幫助我們:mock對象。Mock對象也就是真實對象在調試期的替代品。

什麼時候需要使用Mock?

關於什麼時候需要Mock對象,Tim Mackinnon給我們了一些建議:

  • 真實對象具有不可確定的行為(產生不可預測的結果,如股票的行情)
  • 真實對象很難被創建(比如具體的web容器)
  • 真實對象的某些行為很難觸發(比如網絡錯誤)
  • 真實情況令程序的運行速度很慢
  • 真實對象有用戶界面
  • 測試需要詢問真實對象它是如何被調用的(比如測試可能需要驗證某個回調函數是否被調用了)
  • 真實對象實際上並不存在(當需要和其他開發小組,或者新的硬件系統打交道的時候,這是一個普遍的問題)

如何使用Mock?

.NET Mock Framework有哪些,可以看看下面幾個網頁:

  • .NET Mocking Framework對比
  • What C# mocking framework to use?
  • The Fakes Framework in Visual Studio 2012

關於Mock框架的實現方式,大概有兩種:基於動態代理實現;基於編譯時靜態織入實現。各個框架的用法看一下介紹很快就可以掌握了,關鍵是如何使用各種mock技術,存在的爭論主要有下面幾個:

  • 像Typemock、Moles、The Fakes Framework這類靜態織入技術的框架,可以支持對Sealed Class、Non-Abstract Method、Non-Virtual Method、Static Method的Mock。有些人覺得這很強大,有些人覺得這反倒不好,他們認為像Moq、Rhino Mocks這類的框架,正因為不支持前面說的四類情況的mock,強迫項目必須實現依賴倒置,從而降低了項目的耦合性,以達到較高的可測試性以及可維護性。
  • 在使用動態代理方式的Mock框架時候,為了“可測試性”,protected方法必須是virtual的,因為我們需要在子類中進行override。同理,Mock框架能夠輔助的方法也必須是virtual的,即使是一個public方法。那麼,您覺得這是為了可測試性而做出的讓步嗎?或者換句話說,您覺得,一個不可以override的protected方法,但是會影響到其他公開接口的功能,這是不是一個合理的設計呢?如果這是一個合理的設計,又不想作出這樣的讓步……我們又該怎麼做呢?(這段話摘自老趙的“與protected成員有關的單元測試方式”)
  • 在使用動態代理方式的Mock框架時候,為了測試一些Non-Abstract Method、Non-Virtual Method、Static Method,提供一個被測方法/類的Wrapper,封裝對無法直接訪問方法的調用,是否合適?做法參考:
    http://blog.zhaojie.me/2009/08/unit-test-protected-method.html#comment_iX2whQ8q04I003i2
    http://blog.zhaojie.me/2009/08/unit-test-protected-method.html#comment_iX2whQ8q04I003hi


參考:

  • 簡​述​M​o​c​k
  • 使用Mono.Cecil解決無法Mock非虛方法和密閉類的問題
  • protected成員有關的單元測試方式
  • 如何 Mock 非虛方法和密封類?
  • 了解何時使用 Override 和 New 關鍵字(C# 編程指南)
  • C# 類教程-多態性

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved