Python mock

官方文檔 : https://docs.python.org/dev/library/unittest.mock.html

Mock

Mock類庫是一個專門用于在unittest過程中制作(偽造)和修改(篡改)測試對象的類庫,制作和修改的目的是避免這些對象在單元測試過程中依賴外部資源(網(wǎng)絡資源,數(shù)據(jù)庫連接,其它服務以及耗時過長等).

安裝

Python 2.7中沒有集成mock庫,Python3中的unittest中集成了mock庫.

Python 2.7環(huán)境下pip安裝:

$ pip install mock

快速使用

>>> from mock import MagicMock      #MagicMock為Mock的子類
>>> thing = ProductionClass()
>>> thing.method = MagicMock(return_value=3)
#指定返回3
>>> thing.method(3, 4, 5, key='value')
3
>>> thing.method.assert_called_with(3, 4, 5, key='value')
#斷言輸入是否為3,4,5,key='value',否則報錯

示例

#module.py

class Count():

    def add(self, a, b):
        return a + b

測試用例:

from unittest import mock
import unittest
from module import Count


class MockDemo(unittest.TestCase):

    def test_add(self):
        count = Count()
        count.add = mock.Mock(return_value=13, side_effect=count.add)
        result = count.add(8, 8)
        print(result)
        count.add.assert_called_with(8, 8)
        self.assertEqual(result, 16)

if __name__ == '__main__':
    unittest.main()

count.add = mock.Mock(return_value=13, side_effect=count.add)

side_effect參數(shù)和return_value是相反的。它給mock分配了可替換的結果,覆蓋了return_value。簡單的說,一個模擬工廠調用將返回side_effect值,而不是return_value。

所以,設置side_effect參數(shù)為Count類add()方法,那么return_value的作用失效。

測試依賴

例如,我們要測試A模塊,然后A模塊依賴于B模塊的調用。但是,由于B模塊的改變,導致了A模塊返回結果的改變,從而使A模塊的測試用例失敗。其實,對于A模塊,以及A模塊的用例來說,并沒有變化,不應該失敗才對。

通過mock模擬掉影響A模塊的部分(B模塊)。至于mock掉的部分(B模塊)應該由其它用例來測試。

# function.py
def add_and_multiply(x, y):
    addition = x + y
    multiple = multiply(x, y)
    return (addition, multiple)


def multiply(x, y):
    return x * y

然后,針對 add_and_multiply()函數(shù)編寫測試用例。func_test.py

import unittest
import function


class MyTestCase(unittest.TestCase):

    def test_add_and_multiply(self):
        x = 3
        y = 5
        addition, multiple = function.add_and_multiply(x, y)
        self.assertEqual(8, addition)
        self.assertEqual(15, multiple)


if __name__ == "__main__":
    unittest.main()

add_and_multiply()函數(shù)依賴了multiply()函數(shù)的返回值。如果這個時候修改multiply()函數(shù)的代碼。

def multiply(x, y):
    return x * y + 3

python3 func_test.py
F
======================================================================
FAIL: test_add_and_multiply (main.MyTestCase)
Traceback (most recent call last):
File "fun_test.py", line 19, in test_add_and_multiply
self.assertEqual(15, multiple)
AssertionError: 15 != 18
Ran 1 test in 0.000s
FAILED (failures=1)

測試用例運行失敗了,然而,add_and_multiply()函數(shù)以及它的測試用例并沒有做任何修改,罪魁禍首是multiply()函數(shù)引起的,我們應該把 multiply()函數(shù)mock掉。

import unittest
from unittest.mock import patch
import function


class MyTestCase(unittest.TestCase):

    @patch("function.multiply")
    def test_add_and_multiply2(self, mock_multiply):
        x = 3
        y = 5
        mock_multiply.return_value = 15
        addition, multiple = function.add_and_multiply(x, y)
        mock_multiply.assert_called_once_with(3, 5)

        self.assertEqual(8, addition)
        self.assertEqual(15, multiple)


if __name__ == "__main__":
    unittest.main()


@patch("function.multiply")

patch()裝飾/上下文管理器可以很容易地模擬類或對象在模塊測試。在測試過程中,您指定的對象將被替換為一個模擬(或其他對象),并在測試結束時還原。

這里模擬function.py文件中multiply()函數(shù)。

def test_add_and_multiply2(self, mock_multiply):

在定義測試用例中,將mock的multiply()函數(shù)(對象)重命名為 mock_multiply對象。

mock_multiply.return_value = 15

設定mock_multiply對象的返回值為固定的15。

ock_multiply.assert_called_once_with(3, 5)

檢查ock_multiply方法的參數(shù)是否正確。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

  • Startup 單元測試的核心價值在于兩點: 更加精確地定義某段代碼的作用,從而使代碼的耦合性更低 避免程序員寫出...
    wuwenxiang閱讀 10,238評論 1 27
  • 單元測試 什么是單元 單元測試(unit testing),是指對軟件中的最小可測試單元(一個模塊、一個函數(shù)或者一...
    PPMac閱讀 6,785評論 0 19
  • 最近做發(fā)短信的service的時候,與短信相關的測試需要mock,于是碰到以下問題。例如有三個模塊a和b和test...
    doyoubi閱讀 1,248評論 0 3
  • Spring Cloud為開發(fā)人員提供了快速構建分布式系統(tǒng)中一些常見模式的工具(例如配置管理,服務發(fā)現(xiàn),斷路器,智...
    卡卡羅2017閱讀 136,697評論 19 139
  • 今日兩市再次低開,創(chuàng)業(yè)板開盤即跌破了前期的低點,創(chuàng)出了兩年以來的新低,隨后就是一路的震蕩,至收盤,滬指收于3093...
    股海蒼穹閱讀 174評論 0 0

友情鏈接更多精彩內容