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

Python中如何测试被Mock类的实例化情况?

问题描述

需要为bar模块的Bar类编写无外部依赖的单元测试,所有依赖通过Mock实现。当Bar传入参数7时,会实例化foo.Foo作为成员,但测试不想导入foo或foo.Foo。当前Mock配置后,调用mock_foo.assert_called()验证失败,报错“Expected 'mock' to have been called.”。

问题原因

你Mock的层级错了。bar模块里调用的是foo.Foo(即foo模块下的Foo类),但你只替换了bar.foo这个模块对象,并没有替换bar.foo.Foo这个类引用。bar在导入时已经加载了原foo模块,替换bar.foo不会自动修改它内部的Foo属性,所以实际调用的还是原foo.Foo,你的Mock根本没被触发。

解决方案

下面是两种正确的实现方式:

方法一:直接替换bar.foo.Foo为Mock对象

直接把bar模块里的foo.Foo替换成Mock类,这样Bar实例化时调用foo.Foo(7)就会触发这个Mock。

修改后的测试代码:

#!/usr/bin/env python3
import unittest
from unittest import mock

import bar


class MyTest(unittest.TestCase):
    def test_bar(self):
        # 替换bar模块内的foo.Foo为Mock类
        mock_foo_class = mock.Mock()
        bar.foo.Foo = mock_foo_class

        b = bar.Bar(7)

        # 验证Foo类被调用一次,传入参数7
        mock_foo_class.assert_called_once_with(7)
        # 验证b.y是Mock实例化后的对象
        self.assertIsInstance(b.y, mock.Mock)

    def test_int(self):
        b = bar.Bar(8)
        self.assertIsInstance(b.y, int)


if __name__ == '__main__':
    unittest.main()

方法二:使用unittest.mock.patch装饰器(更规范)

用patch直接拦截bar.foo.Foo,测试结束后自动恢复原引用,避免污染其他测试用例,写法更简洁。

修改后的测试代码:

#!/usr/bin/env python3
import unittest
from unittest import mock

import bar


class MyTest(unittest.TestCase):
    @mock.patch('bar.foo.Foo')
    def test_bar(self, mock_foo_class):
        b = bar.Bar(7)

        # 验证Foo类被调用一次,参数为7
        mock_foo_class.assert_called_once_with(7)
        self.assertIsInstance(b.y, mock.Mock)

    def test_int(self):
        b = bar.Bar(8)
        self.assertIsInstance(b.y, int)


if __name__ == '__main__':
    unittest.main()

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.01 14:25:22