如何在Python中创建具备内部状态的自定义Mock对象
嘿,我完全懂你的需求——你需要一个能模拟硬件接口的Mock类,既要保留读写内部状态的能力,又要让那些没明确实现的方法调用不抛出异常,要么返回固定值比如0,要么返回MagicMock实例对吧?咱们来改造你的代码,分两种场景给你解决方案:
方案1:未定义方法返回固定值(比如0)
你可以利用Python的__getattr__魔法方法——当代码尝试访问类中不存在的属性(包括方法)时,这个方法会被自动调用。我们可以在里面返回一个通用的函数,不管传入什么参数都返回你想要的固定值。
修改后的代码如下:
class MockClass(): def __init__(self): self.my_list = [0]*10 def write(self, index, value): self.my_list[index] = value def read(self, index): return self.my_list[index] def __getattr__(self, name): # 对于任何未定义的方法,返回一个始终返回0的函数 def dummy_method(*args, **kwargs): return 0 return dummy_method
这样一来,当你调用mock_instance.function_yet_to_be_defined_wont_throw_exception("some_random_arg")时,会自动触发__getattr__,返回那个dummy_method,执行后就给你返回0,完全不会报错。
方案2:未定义方法返回MagicMock实例
如果你希望未定义的方法也能像标准MagicMock那样支持链式调用或者其他Mock特性,可以让你的MockClass继承自unittest.mock.MagicMock,然后重写你需要自定义逻辑的read和write方法就行——因为MagicMock本身就会自动为未定义的方法生成Mock实例,不会抛出异常。
代码示例:
from unittest.mock import MagicMock class MockClass(MagicMock): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.my_list = [0]*10 def write(self, index, value): self.my_list[index] = value def read(self, index): return self.my_list[index]
这个方案里,你的读写方法完全保留了自定义的内部状态逻辑,而其他未定义的方法调用时,会自动返回MagicMock实例,比如你调用mock_instance.some_undefined_method().another_call()也不会报错,和标准Mock的行为一致。
测试你的应用代码
不管用上面哪种方案,你的测试代码都能正常工作(注意修正原代码里导入的小问题):
from your_module import MockClass mock_instance = MockClass() # 正常写入值到内部列表 mock_instance.write(index=1, value=10) # 正常读取值,var会是10 var = mock_instance.read(index=1) # 调用未定义的方法,不会抛出异常 mock_instance.function_yet_to_be_defined_wont_throw_exception("some_random_arg")
两种方案按需选就行——如果只是需要简单的固定返回值,方案1足够轻量;如果需要更多Mock的灵活特性,方案2更合适。
备注:内容来源于stack exchange,提问作者generic purple turtle

