1. 程式人生 > 其它 >python文件2-unittest單元測試之mock.patch

python文件2-unittest單元測試之mock.patch

介紹mock裡面另一種實現方式,patch裝飾器的使用,patch() 作為函式裝飾器,為您建立模擬並將其傳遞到裝飾函式

patch簡介

1.unittest.mock.patch(target,new = DEFAULT,spec = None,create = False,spec_set = None,autospec = None,new_callable = None,** kwargs )

  • target引數必須是一個str,格式為'package.module.ClassName',
    注意這裡的格式一定要寫對,如果你的函式或類寫在pakege名稱為a下,b.py腳本里,有個c的函式(或類),那這個引數就寫“a.b.c”

  • new引數如果沒寫,預設指定的是MagicMock

  • spec=True或spec_set=True,這會導致patch傳遞給被模擬為spec / spec_set的物件

  • new_callable允許您指定將被呼叫以建立新物件的不同類或可呼叫物件。預設情況下MagicMock使用。

函式案例講解

1.新建一個temple.py,寫入以下程式碼

# 儲存為temple.py

# coding:utf-8

def zhifu():
    '''假設這裡是一個支付的功能,未開發完
    支付成功返回:{"result": "success", "reason":"null"}
    支付失敗返回:{"result": "fail", "reason":"餘額不足"}
    reason返回失敗原因
    '''
    pass

def zhifu_statues():
    '''根據支付的結果success or fail,判斷跳轉到對應頁面'''
    result = zhifu()
    print(result)
    try:
        if result["result"] == "success":
            return "支付成功"
        elif result["result"] == "fail":
            print("失敗原因:%s" % result["reason"])
            return "支付失敗"
        else:
            return "未知錯誤異常"
    except:
        return "Error, 服務端返回異常!"

2.用mock.patch實現如下:

# coding:utf-8
from unittest import mock
import unittest
import temple

class Test_zhifu_statues(unittest.TestCase):
    '''單元測試用例'''

    @mock.patch("temple.zhifu")
    def test_01(self, mock_zhifu):
        '''測試支付成功場景'''
        # 方法一:mock一個支付成功的資料
        # temple.zhifu = mock.Mock(return_value={"result": "success", "reason":"null"})

        # 方法二:mock.path裝飾器模擬返回結果
        mock_zhifu.return_value = {"result": "success", "reason":"null"}
        # 根據支付結果測試頁面跳轉
        statues = temple.zhifu_statues()
        print(statues)
        self.assertEqual(statues, "支付成功")

    @mock.patch("temple.zhifu")
    def test_02(self, mock_zhifu):
        '''測試支付失敗場景'''
        # mock一個支付成功的資料

        mock_zhifu.return_value = {"result": "fail", "reason": "餘額不足"}
        # 根據支付結果測試頁面跳轉
        statues = temple.zhifu_statues()
        self.assertEqual(statues, "支付失敗")

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

類和方法案例

1.如果前面的temple.py裡面不是函式,是寫的類和方法,如何去使用mock?

# 儲存為temple.py

# coding:utf-8
class Zhifu():
    def zhifu(self):
        '''假設這裡是一個支付的功能,未開發完
        支付成功返回:{"result": "success", "reason":"null"}
        支付失敗返回:{"result": "fail", "reason":"餘額不足"}
        reason返回失敗原因
        '''
        pass

class Statues():
    def zhifu_statues(self):
        '''根據支付的結果success or fail,判斷跳轉到對應頁面'''
        result = Zhifu().zhifu()
        print(result)
        try:
            if result["result"] == "success":
                return "支付成功"
            elif result["result"] == "fail":
                print("失敗原因:%s" % result["reason"])
                return "支付失敗"
            else:
                return "未知錯誤異常"
        except:
            return "Error, 服務端返回異常!"

2.用例設計如下

# coding:utf-8
from unittest import mock
import unittest
from temple_class import Zhifu,Statues
# 作者:上海-悠悠 QQ交流群:588402570

class Test_zhifu_statues(unittest.TestCase):
    '''單元測試用例'''

    @mock.patch("temple_class.Zhifu")
    def test_01(self, mock_Zhifu):
        '''測試支付成功場景'''
        a = mock_Zhifu.return_value  # 先返回例項,對類名稱替換
        # 通過例項呼叫方法,再對方法的返回值替換
        a.zhifu.return_value = {"result": "success", "reason":"null"}
        # 根據支付結果測試頁面跳轉
        statues = Statues().zhifu_statues()
        print(statues)
        self.assertEqual(statues, "支付成功")

    @mock.patch("temple_class.Zhifu")
    def test_02(self, mock_Zhifu):
        '''測試支付失敗場景'''
        b = mock_Zhifu.return_value  # 先返回例項,對類名稱替換
        # 通過例項呼叫方法,再對方法的返回值替換
        b.zhifu.return_value = {"result": "fail", "reason": "餘額不足"}
        # 根據支付結果測試頁面跳轉
        statues = Statues().zhifu_statues()
        print(statues)
        self.assertEqual(statues, "支付失敗")

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

3.相當於函式來說,這裡主要多一步,要先對類的名稱進行mock一次"a = mock_Zhifu.return_value",再通過例項去呼叫方法