簡體   English   中英

class 方法中的模擬/補丁特定 object 方法

[英]Mock/Patch specific object method inside a class method

我知道標題很混亂,但為了清楚起見,我創建了一個我必須轉置的樣本:

假設我在class_file.py中有這段代碼

class CarDealership:
    def allow_car_out_of_the_dealership(self, car):
        logger.info(f"Driving out of the dealership")
        
        drivers_license = car.driver.wallet.get_drivers_license()

        if drivers_license:
            try:
                allow_car_removal(car, drivers_license)
            except:
                deny_car_removal(car, drivers_license)

我正在嘗試測試調用deny_car_removal方法的情況。 get_valid_license()是特定於driver.wallet的方法,不會以任何方式、形狀或形式在class_file.py中導入或引用。

問題是,如果get_valid_license在實際情況下沒有返回任何有效的東西,那么代碼會采用完全不同的方式。 我正在嘗試修補drivers_license ,以便最終將其帶到我需要的地步。

我猜test_class_file.py應該是這樣的:

class CarDealershipTests(BaseTestCase):
    @patch('class_file.CarDealership.deny_car_removal')
    def test_deny_car_removal(self):
        # something here
        self.assertTrue(mock_deny_car_removal.called)

我通過查看其他 StackOverflow 答案嘗試了一些事情,但沒有奏效:

  • 在測試設置中,在模擬的car中模擬一個完整的driver實例,如下所示:
    def setUp(self) -> None:
        self._create_car
    
    def _create_car(self):
        car = Car()
        car.driver = MagicMock()
  • 嘗試使用@patch.object(class_file.CarDealership.allow_car_out_of_the_dealership, "car.driver.wallet.get_valid_license")
  • 嘗試使用@patch.object(class_file.CarDealership.allow_car_out_of_the_dealership, "drivers_license")
  • 嘗試使用@patch("class_file.CarDealership.allow_car_out_of_the_dealership.car.driver.wallet.get_valid_license")
  • 嘗試使用@patch("class_file.CarDealership.allow_car_out_of_the_dealership.drivers_license")

假設您有一個文件,其內容如下所示:

import logging

logger = logging.getLogger(__name__)

class CarRemovalFailure(BaseException):
    pass


class CarDealership:
    def allow_car_out_of_the_dealership(self, car):
        logger.info("Driving out of the dealership")
        
        drivers_license = car.driver.wallet.get_drivers_license()

        if drivers_license:
            try:
                allow_car_removal(car, drivers_license)
            except CarRemovalFailure:
                deny_car_removal(car, drivers_license)

為了調用deny_car_removal ,我們需要allow_car_removal拋出一個Exception 這可以通過使用Mock object 的side_effect屬性輕松完成。

我沒有在這個測試中加入任何設置/拆卸,而是說明side_effect是如何工作的,以及它是如何最終調用deny_car_removal的。

from unittest.mock import MagicMock, patch
from class_file import CarDealership, CarRemovalFailure


@patch("class_file.allow_car_removal")
@patch("class_file.deny_car_removal")
def test_deny_car(mock_deny, mock_allow):
    mock_allow.side_effect = CarRemovalFailure("Failed!")
    car = MagicMock()
    cd = CarDealership()

    cd.allow_car_out_of_the_dealership(car)

    car.driver.wallet.get_drivers_license.assert_called_once()
    mock_deny.assert_called_once()

運行時輸出以下內容:

============================= test session starts ==============================
platform darwin -- Python 3.9.1, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
rootdir: ****
collected 1 item                                                               

tests/test_car.py .                                                      [100%]

============================== 1 passed in 0.05s ===============================

在您的示例中,您可能不想在嘗試測試邏輯時修補deny_car_removal ,但由於我不知道那可能是什么,所以我最終修補了它。 這樣做的目的是為了說明實際上 function 確實被調用了。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM