我有一个类似于以下示例的 Python 类结构:
class Foo:
def start(self):
# do something
class FooBar(Foo):
def __init__(self, param):
self.param = param
def run(self):
# do something else
class ProductionClass:
def use_foobar(self):
foo = FooBar("string")
foo.start()
现在我想编写一个测试,其中模拟
start
上的 FooBar
方法(继承自 Foo
),以便调用直接在 run
中定义的 FooBar
方法。
我试过这样:
def test_something(self):
self.foobar_patcher = patch.object(FooBar, 'start', side_effect=self.mock_start)
self.foobar_patcher.start()
ProductionClass().use_foobar()
def mock_start(self):
the_production_class_instance.run()
在此示例中,
the_production_class_instance
是调用 start()
方法的 FooBar 实例,但我似乎找不到获取此实例的方法。该实例在ProductionClass().use_foobar()
内部创建,并在使用后丢弃,因此没有真正的方法从外部访问它。
有没有办法通过单元测试来实现这一点?
为了解决您的问题,我已将您的
ProductionClass
修改如下:
class ProductionClass:
def __init__(self):
self.foo = FooBar("string")
def use_foobar(self):
self.foo.start()
差异是:
__init__()
,其中创建了属性 foo
作为 FooBar
use_foobar()
中只调用了继承自start()
的FooBar
的方法Foo
。所以我已将您的生产代码保存在以下文件
prod.py
中(除了在方法Foo
和FooBar
中引入print()
指令之外,类start()
和run()
保持不变) :
class Foo:
def start(self):
# for execute the code I have substituted 'do_something' with a print()
print("Foo.start() exec")
class FooBar(Foo):
def __init__(self, param):
self.param = param
def run(self):
# for execute the code I have substituted 'do_something' with a print()
print("FooBar.run() exec")
class ProductionClass:
def __init__(self):
self.foo = FooBar("string")
def use_foobar(self):
self.foo.start()
经过之前的修改,我认为下面的测试代码可以满足您的要求(代码保存在文件中
test_code.py
):
import unittest
from unittest.mock import patch
from prod import ProductionClass
class MyTestCase(unittest.TestCase):
def test_something(self):
prod_class = ProductionClass()
foo_instance = prod_class.foo
with patch.object(foo_instance, 'start') as mock_start:
mock_start.start = foo_instance.run()
prod_class.use_foobar()
if __name__ == '__main__':
unittest.main()
如果我使用以下命令在终端中执行测试代码:
/path/to/python/interpreter/python /path/to/test/file/test_prod.py
我得到以下输出:
FooBar.run() exec
.
----------------------------------------------------------------------
Ran 1 test in 0.001s
OK
这证明它是执行
run()
的方法FooBar
而不是start()
的方法Foo
。