【问题标题】:How to patch built-in/extension types in python using mockito?如何使用 mockito 修补 python 中的内置/扩展类型?
【发布时间】:2025-11-23 16:45:02
【问题描述】:

在 python 中使用mockito 进行单元测试时,我遇到了一个我找不到解决方案的问题。我正在尝试修补给定类方法中io.BytesIO 的使用。以下代码显示了出现问题的简化版本:

from mockito import mock, patch, when
from io import BytesIO

class Foo:
    def bar(self):
        buffer = io.BytesIO()
        # ...
        return buffer.getvalue()

def test_foo():
    bytesIO_mock = mock(strict=True)
    when(bytesIO_mock).getvalue().thenReturn('data')

    patch(BytesIO.__new__, lambda: bytesIO_mock)
    result = Foo().bar()
    assert result == 'data'

执行测试时出现以下错误:

/venv/lib/python3.6/site-packages/mockito/mockito.py:270: in patch
when2(fn, Ellipsis).thenAnswer(replacement)
/venv/lib/python3.6/site-packages/mockito/mockito.py:245: in when2
return invocation.StubbedInvocation(theMock, name)(*args, **kwargs)
/venv/lib/python3.6/site-packages/mockito/invocation.py:284: in __call__
self.mock.stub(self.method_name)
/venv/lib/python3.6/site-packages/mockito/mocking.py:117: in stub
self.replace_method(method_name, original_method)
/venv/lib/python3.6/site-packages/mockito/mocking.py:108: in replace_method
self.set_method(method_name, new_mocked_method)

self = <mockito.mocking.Mock object at 0x10d50cb38>, method_name = '__new__'
new_method = <function Mock.replace_method.<locals>.new_mocked_method at 0x10d753e18>

    def set_method(self, method_name, new_method):
>       setattr(self.mocked_obj, method_name, new_method)
E       TypeError: can't set attributes of built-in/extension type '_io.BytesIO'

/venv/lib/python3.6/site-packages/mockito/mocking.py:74: TypeError

这个问题有什么解决办法吗,还是只是在python中无法模拟某些对象?

【问题讨论】:

    标签: python unit-testing mocking mockito


    【解决方案1】:

    您可以简单地模拟来自io.BytesIO() 的响应,而不是使用patch,如下所示:

    def test_foo():
        bytesIO_mock = mock(strict=True)
    
        when(bytesIO_mock).getvalue().thenReturn('data')
        when(io).BytesIO().thenReturn(bytesIO_mock)
    
        result = Foo().bar()
        assert result == 'data'
    

    根据经验,Python 中的所有对象都可以模拟as everything in Python is an object。如果你不能模拟它,可能是由于正在使用的测试库/框架的限制。

    【讨论】:

      最近更新 更多