最近,我必須使用 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 模組。它在測試中用於臨時用模擬或其他值替換給定物件的屬性。
參數
透過這種方式,我們可以在我們的裝置中建立模擬變數。
閱讀有關 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
希望這有幫助! :)
以上是模擬 Python 類別的詳細內容。更多資訊請關注PHP中文網其他相關文章!