」工欲善其事,必先利其器。「—孔子《論語.錄靈公》
首頁 > 程式設計 > 模擬 Python 類別

模擬 Python 類別

發佈於2024-11-03
瀏覽:809

Mocking Python Classes

最近,我必須使用 Pytest 為 Python 模組編寫單元測試。此模組包含一個類,其他類在其建構函數中初始化。

像往常一樣,我為此類創建了一個固定裝置,以便輕鬆為每個類別方法編寫測試。此時,當我嘗試模擬建構函數中啟動的不同類別時,我遇到了一些問題。模擬不起作用,這些類別的實例仍在建立中。

經過一些研究並結合我在網路上找到的一些不同的解決方案,我想分享我如何設法模擬課程。

解決方案

這是我嘗試模擬的類別的範例:

class ClassA:
    def __init__(self):
        self.class_b = ClassB()
        self.class_c = ClassC()
        self.count = 0

我們希望在測試期間為此類的每個欄位設定一個值。該值可以是 None 或類別模擬,但我們不希望啟動 ClassB 和 ClassC 類別。

在我們的例子中,讓我們決定 self.class_b 和 self.class_c 應該是模擬:

@pytest.fixture
def mock_class_b():
    class_b = Mock(spec=ClassB)
    return class_b

@pytest.fixture
def mock_class_c():
    class_c = Mock(spec=ClassC)
    return class_c

因此,此類符合我們目標的固定裝置如下所示:

@pytest.fixture
def class_a_mock(mock_class_b, mock_class_c):
    with patch.object(target=ClassA, attribute="__init__", return_value=None) as mock_init:
        class_a = ClassA()
        class_a.class_b = mock_class_b
        class_a.class_c = mock_class_c
        class_b.count = 0
        return class_a

重要的部分是如何使用patch.object函數,該函數來自Python中的unittest.mock模組。它在測試中用於臨時用模擬或其他值替換給定物件的屬性。

參數

  1. target=ClassA:我們要修補其屬性的物件(通常是類別)。
  2. attribute="__init__": 我們要修補的屬性的名稱。
  3. return_value=None:用不執行任何操作的函數取代 __init__ 方法

透過這種方式,我們可以在我們的裝置中建立模擬變數。
閱讀有關 patch.object

的更多信息

測驗技巧

我寫這個教學是為了這種情況,無論出於何種原因,我們都無法更改A類的程式碼。但是,我通常建議如果可能的話修改程式碼,不是為了改變邏輯,而是為了使其更易於測試.

以下是如何修改 A 類以使其更易於測試的一些示例:

選項 1: 將 B 類和 C 類的實例作為參數傳遞。
這樣,當我們編寫固定裝置時,我們可以傳遞模擬而不是實例。

class ClassA:
    def __init__(self, class_b_instance, class_c_instance):
        self.class_b = class_b_instance
        self.class_c = class_c_instance
        self.count = 0

選項 2: 建立一個指示測試模式的布林變數。
這樣我們就可以決定A類別的哪些欄位在啟動時會或不會取得值。

class ClassA:
    def __init__(self, test_mode=False):
        if not test_mode:
            self.class_b = ClassB()
            self.class_c = ClassC()
        self.count = 0

選項 3: 在單獨的方法中進行類別啟動。
這種方法使我們可以選擇避免在測試模組中呼叫 set_class_variables。

class ClassA:
    def __init__(self):
        self.class_b = None
        self.class_c = None
        self.count = None

    def set_class_variables(self):
        self.class_b = ClassB()
        self.class_c = ClassC()
        self.count = 0

希望有幫助! :)

版本聲明 本文轉載於:https://dev.to/chen_ashkenazi/mocking-python-classes-4h96?1如有侵犯,請聯絡[email protected]刪除
最新教學 更多>

免責聲明: 提供的所有資源部分來自互聯網,如果有侵犯您的版權或其他權益,請說明詳細緣由並提供版權或權益證明然後發到郵箱:[email protected] 我們會在第一時間內為您處理。

Copyright© 2022 湘ICP备2022001581号-3