unittest mock基本使用


 

mock介紹

mock允許用模擬對象替換系統中真實對象,並對它們已使用的方式進行斷言。

在進行單元測試的時候,會遇到以下問題:
•接口的依賴;
•外部接口調用;
•測試環境非常復雜。
且單元測試應該只針對當前單元進行測試, 所有的內部或外部的依賴應該是穩定的, 已經在別處進行測試過的.使用mock 就可以對外部依賴組件實現進行模擬並且替換掉, 從而使得單元測試將焦點只放在當前的單元功能。

以下一個簡單的示例:

調用mock並指定 reutrn_value 創建一個mock對象,然后mock 掉 say_hello 函數對象后,這個方法的一切動作,比如 print 就變得沒有意義了,因為最后這個方法只會做一件事就是返回我們為其指定的返回值。

from unittest.mock import Mock


def say_hello(word):
    print(f"Hello {word}")

say_hello("China")
mock=Mock(return_value="PYTHON OH YEAH")
say_hello=mock
say_hello("China")

mock模塊的基本使用

return_vaule 

mock 對象的 return_vaule 的作用:它將忽略 mock 對象的行為,指定其返回值。

modular.py

class Count():

    def add(self):
        pass

mock_demo01.py

from unittest import mock
import unittest

from modular import Count

# test Count class
class TestCount(unittest.TestCase):

    def test_add(self):
        count = Count()
        count.add = mock.Mock(return_value=13)
        result = count.add(8,5)
        self.assertEqual(result,13)

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

假設Count計算類沒有實現,原本add() 方法要實現兩數相加。但這個功能還沒有完成。這時就可以借助mock對其進行測試。  

count = Count()

首先,調用被測試類Count() 。

count.add = mock.Mock(return_value=7)

通過Mock類模擬被調用的方法add()方法,return_value 定義add()方法的返回值。

result = count.add(2,5)

接下來,相當於在正常的調用add()方法,傳兩個參數2和5,然后會得到相加的結果7。然后,7的結果是我們在上一步就預先設定好的。

self.assertEqual(result,7)

最后,通過assertEqual()方法斷言,返回的結果是否是預期的結果7。

side_effect

mock 對象的side_effect 的作用:通過side_effect指定mock對象的副作用,這個副作用就是當你調用這個mock對象時會調用的函數,也可以選擇拋出一個異常,來對程序的錯誤狀態進行測試。

from unittest.mock import Mock


def say_hello(word):
    print(f"Hello {word}")


mock=Mock()
#指定為函數
mock.side_effect  = say_hello
mock('china')

#指定為異常
mock.side_effect  = KeyError('This is b') #Exception("Raise Exception")
mock()

 另外也可以通過為side_effect指定一個列表,這樣在每次調用時會依次返回,如下:

from unittest.mock import Mock


mock=Mock(side_effect = [1, 2, 3])
print(mock())
print(mock())
print(mock())

patch裝飾器

  它是一個裝飾器,需要把你想模擬的函數寫在里面,然后在后面的單元測試案例中為它賦一個具體實例,再用 return_value 來指定模擬的這個函數希望返回的結果就可以了,后面就是正常單元測試代碼。

@mock.pathc.object(類名,“類中函數名”)

from unittest import mock
import unittest

class Count():

    def add(self):
        pass


# test Count class
class TestCount(unittest.TestCase):

    @mock.patch.object(Count, "add")
    def test_add(self, mock_add):
        mock_add. return_value = 13
        result = mock_add()
        self.assertEqual(result,13)

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

@mock.pathc(模塊名,“函數名”)

linux_tool.py

import re
 
def send_shell_cmd():
    return "Response from send_shell_cmd function"
 
def check_cmd_response():
    response = send_shell_cmd()
    print("response: {}".format(response))
    return re.search(r"mock_send_shell_cmd", response)

測試代碼:

from unittest import TestCase, mock
import linux_tool
 
class TestLinuxTool(TestCase):
    def setUp(self):
        pass
 
    def tearDown(self):
        pass
 
    @mock.patch("linux_tool.send_shell_cmd")
    def test_check_cmd_response(self, mock_send_shell_cmd):
        mock_send_shell_cmd.return_value = "Response from emulated mock_send_shell_cmd function"
 
        status = linux_tool.check_cmd_response()
        print("check result: %s" % status)
        self.assertTrue(status)

如果 patch 多個外部函數,那么調用遵循自下而上的規則,比如:

@mock.patch("function_C")
@mock.patch("function_B")
@mock.patch("function_A")
def test_check_cmd_response(self, mock_function_A, mock_function_B, mock_function_C):
    mock_function_A.return_value = "Function A return"
    mock_function_B.return_value = "Function B return"
    mock_function_C.return_value = "Function C return"
 
    self.assertTrue(re.search("A", mock_function_A()))
    self.assertTrue(re.search("B", mock_function_B()))
    self.assertTrue(re.search("C", mock_function_C()))

一個示例

Count類中add_and_multiply依賴multiply,由於multiply並沒有實現,這時候可以使用mock替換multiply:

from unittest import mock
import unittest

class Count():

    def add_and_multiply(self,x, y):
        addition = x + y
        multiple = self.multiply(x, y)
        return (addition, multiple)

    def multiply(self,x, y):
        pass


# test Count class
class TestCount(unittest.TestCase):

    @mock.patch.object(Count, "multiply")
    def test_add(self, mock_multiply):
        mock_multiply. return_value = 40
        count = Count()
        addition,multiple = count.add_and_multiply(5,8)
        self.assertEqual(addition,13)
        self.assertEqual(multiple, 40)

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

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM