如何Mock外部模块中的基类以实现Python单元测试?
The issue you're hitting is that replacing the entire external_module with a MagicMock causes your MyClass to inherit from a Mock class, which dynamically overrides method calls even when your subclass defines its own methods. Let's break down why this happens and fix it.
Why Your Current Code Fails
When you run sys.modules['external_module'] = MagicMock(), every member of external_module (including ExternalClass) becomes a MagicMock instance. MagicMock has a special behavior: any attribute or method you access on it (or its subclasses) returns a new MagicMock object—even if your subclass like MyClass defines its own version of that method. That's why calling test_method() returns a Mock instead of "successful".
Solution 1: Replace the Mock Base Class with a Plain Object
The simplest fix is to swap out the mocked ExternalClass with a regular class (like object) that won't interfere with your subclass's methods. Here's how to adjust your test code:
import sys import unittest from unittest.mock import MagicMock # Mock the external module initially sys.modules['external_module'] = MagicMock() # Replace ExternalClass with a plain object so MyClass inherits from something harmless sys.modules['external_module'].ExternalClass = object # Now safely import MyClass from my_class import MyClass class TestMyClass(unittest.TestCase): def test_first(self): my_class = MyClass() result = my_class.test_method() self.assertEqual(result, "successful") if __name__ == '__main__': unittest.main()
Solution 2: Use unittest.mock.patch for Targeted Mocking
For a more idiomatic approach, use patch to only mock the specific ExternalClass you need, instead of the entire module. This keeps things clean and focused:
import unittest from unittest.mock import patch # Patch ExternalClass before importing MyClass to avoid import errors with patch('external_module.ExternalClass'): from my_class import MyClass class TestMyClass(unittest.TestCase): def test_first(self): my_class = MyClass() result = my_class.test_method() self.assertEqual(result, "successful") if __name__ == '__main__': unittest.main()
Both solutions work because they ensure MyClass inherits from a class that doesn't override its own methods. The first is quick and straightforward, while the second follows mocking best practices for targeted isolation.
内容的提问来源于stack exchange,提问作者yongnuo

