當前位置:
首頁 > 知識 > 讀懂Python的Mock對象庫(2)

讀懂Python的Mock對象庫(2)

Mock的常規問題

在你的測試中mock對象可能會引入一些問題。有些問題是mock中固有的,而有的是unittest.mock特有的。記住一點,本教程並未提及其他mock的問題。

這裡介紹的問題大多相似,因為它們引起的問題基本相同。在這些情況下,測試斷言沒有什麼作用。雖然每個mock的目標都有校驗,但是mock本身並沒有。

修改對象介面和拼寫

類和函數定義一直在變化。當對象的介面發生改變時,依賴於該對象的任何mock測試都可能會失效。

例如,你重命名了一個方法但是忘記在測試中mock這個方法並且沒有調用.assert_not_called()做驗證。方法更改後,.assert_not_called()仍然為True,但是斷言沒有用了,因為方法已經不存在了。

無效的測試看似不重要,但是如果它們是你僅有的測試且你認為它們是正常的,這種情況可能對你的應用程序造成嚴重影響。

Mock中一個特有的拼寫錯誤問題會導致測試失敗。當你訪問Mock的成員時,它會創建一個新的介面。所以,如果拼寫錯誤,你可能在無意間創建了一個新的屬性。

如果你調用了.asert_called()而不是.assert_called(),測試程序並不會引發AssertionError,這是因為你在Python mock對象上創建了一個名為asert_called()的新方法,而並不是按預計執行了斷言。

技術細節:有趣的是,assret是assert的一種特殊拼寫錯誤。如果你嘗試訪問以assret(或assert)開頭的屬性,Mock將自動引發AttributeError異常。

當你在自己的代碼庫中mock對象時會出現這些問題,當你mock的對象與外部交互時,則會出現另外的問題。

修改外部依賴

再設想一下,你的代碼向外部API發出請求,這種情況,外部依賴是可以不經你允許而輕易修改的API。

一方面,單元測試是測試代碼中單獨的某一部分組件。所以,mock代碼可以生成請求幫助你在可控條件下測試獨立組件。但是它也存在一些潛在問題。

如果外部依賴修改了自身介面,你的Python mock對象將會失效。如果出現了這種情況(並且介面變更被破壞),你的測試會通過,但是生產代碼會出錯,這是因為你的mock對象覆蓋了介面變更。

不幸的是,unittest.mock並沒有為這種問題提供解決方案,在mock外部依賴時,你必須自行判斷。

以上三種的問題都可能導致測試失效以及潛在的成本問題,因為它們會危及mock的完整性。unittest.mock為處理這些問題提供了一些工具。

利用規範避免常規問題

如上所述,如果修改了對象或者函數定義或者Python mock對象屬性拼寫錯誤,會導致測試出現問題。

出現這些問題是由於當你在訪問Mock的屬性和方法時Mock會創建它們。解決這些問題需要預防Mock創建不符合mock測試預期的對象屬性。

配置Mock時,可以將象規範傳遞給spec參數。spec 接受命名列表或者其他對象,並定義mock的介面。如果你嘗試訪問不屬於該規範的屬性,Mock將引發AttributeError異常。

讀懂Python的Mock對象庫(2)

這裡,你已經指定calendar擁有名為.is_weekday()和.get_holidays()的方法。當你訪問.is_weekday(),它會返回一個Mock對象。當你訪問.create_event()時,該方法與規範不匹配,Mock會引發AttributeError異常。

如果使用對象來配置Mock,規範的工作方式也是相同的。

讀懂Python的Mock對象庫(2)

.is_weekday()對於calendar是可用的,因為你配置了calendar來匹配my_calendar模塊的介面。

此外,unittest.mock提供了自動指定Mock實例介面的快捷方法。

實現自動化規範的一種方法是create_autospec:

讀懂Python的Mock對象庫(2)

一如前文,calendar是Mock的一個實例,其介面與my_calendar匹配。如果你正在使用patch(),你可以向autospec發送參數以獲得相同的結果:

讀懂Python的Mock對象庫(2)

總結

你已經學習了很多關於使用unittest.mock來mock對象的知識!

現在,你可以:

1. 在測試中使用Mock來模擬對象

2. 檢查使用數據以便了解如何應用對象

3. 自定義mock對象的返回值和側面影響

4. 在你的整個代碼庫中使用patch()為對象打補丁

5. 在使用Python mock對象時了解並避免問題

你已經為更好的理解打好了基礎,這可以幫助你更好的構建測試程序。你可以使用mock來深入了解你代碼中其他不清楚的地方。

最後給你留下一個忠告,不要過度使使用mock對象!

利用Python mock對象的強大功能並進行mock很簡單,但這實際上降低了你測試的價值。

如果你有興趣了解更多關於unittest.mock的信息,我建議你閱讀一下它描述極佳的文檔。

英文原文:https://realpython.com/python-mock-library/ 譯者:敦偉

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 Python部落 的精彩文章:

導致機器學習項目失敗的7個原因
改變代碼又不破壞它,使用裝飾器吧

TAG:Python部落 |