You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Python中如何Mock父类方法测试?现有方案存缺陷求优解

Solution for Mocking Parent Class Methods in Python Unit Tests

Got it, let's tackle this problem properly. You're right that some of the approaches you tried have drawbacks, but there are two clean, safe ways to achieve exactly what you need without messing with the control flow of Quux.something or risking unintended side effects.

Core Idea

Python uses dynamic attribute lookup, so we can target specific methods on the parent classes (or even individual instances) without modifying inheritance structures or global super behavior.

Approach 1: Patch Parent Class Methods Globally (Per Test)

This works if you don't mind temporarily replacing the parent class methods for the duration of your test. It's clean and doesn't require modifying your class structure.

Here's a complete test case:

import unittest
from unittest.mock import patch, MagicMock

# Your original class definitions
class Foo(object):
    def something(self, a):
        return a + 1

class Bar(object):
    def mixin(self):
        print("Hello!")

class Quux(Foo, Bar):
    def something(self, a):
        self.mixin()
        return super().something(a) + 2

class TestQuux(unittest.TestCase):
    def test_something_with_class_patches(self):
        # Mock Bar.mixin to verify it gets called
        with patch.object(Bar, 'mixin') as mock_mixin:
            # Mock Foo.something to return a controlled value
            with patch.object(Foo, 'something') as mock_something:
                mock_something.return_value = 10  # Set your desired mock return value

                # Create instance and execute the method under test
                quux_instance = Quux()
                result = quux_instance.something(5)

                # Assertions
                mock_mixin.assert_called_once()  # Verify mixin was invoked
                mock_something.assert_called_once_with(5)  # Verify parent method got correct args
                self.assertEqual(result, 10 + 2)  # Verify final result matches expected logic

Approach 2: Patch Instance-Specific Methods (More Isolated)

If you want to avoid modifying the parent class methods entirely (to prevent side effects on other tests), you can patch the method directly on the Quux instance instead. This is even more isolated:

class TestQuux(unittest.TestCase):
    def test_something_with_instance_patch(self):
        quux_instance = Quux()

        # Mock ONLY this instance's mixin method
        with patch.object(quux_instance, 'mixin') as mock_mixin:
            # Still mock Foo.something (since super() resolves to the parent class)
            with patch.object(Foo, 'something') as mock_something:
                mock_something.return_value = 10
                result = quux_instance.something(5)

                # Same assertions as before
                mock_mixin.assert_called_once()
                mock_something.assert_called_once_with(5)
                self.assertEqual(result, 12)

Why This Works (And Your Previous Approaches Didn't)

  • No inheritance modification: We don't touch __bases__ or redefine class structures, so your original code's logic stays intact.
  • Targeted patching: We only patch the specific methods we care about (Bar.mixin and Foo.something), so other uses of super() in your codebase won't be affected (unlike patching builtins.super).
  • Dynamic lookup: Python resolves self.mixin() and super().something(a) at runtime, so the patched methods are picked up automatically without needing to redefine the Quux class.

Key Notes

  • For super().something(a), we need to patch Foo.something directly because super() in Quux.something resolves to the Foo class's method at runtime.
  • Patching the instance's mixin method (Approach 2) is great for isolation, especially if other tests rely on the original Bar.mixin behavior.

内容的提问来源于stack exchange,提问作者Xophmeister

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.29 08:46:46