Python:单元测试中的模拟
我有类似的情况:Python:单元测试中的模拟,python,unit-testing,mocking,Python,Unit Testing,Mocking,我有类似的情况: class BaseClient(object): def __init__(self, api_key): self.api_key = api_key # Doing some staff. class ConcreteClient(BaseClient): def get_some_basic_data(self): # Doing something. def calculate(self):
class BaseClient(object):
def __init__(self, api_key):
self.api_key = api_key
# Doing some staff.
class ConcreteClient(BaseClient):
def get_some_basic_data(self):
# Doing something.
def calculate(self):
# some staff here
self.get_some_basic_data(param)
# some calculations
然后我想通过模拟获取一些基本数据函数来测试计算函数
我在做这样的事情:
import unittest
from my_module import ConcreteClient
def my_fake_data(param):
return [{"key1": "val1"}, {"key2": "val2"}]
class ConcreteClientTest(unittest.TestCase):
def setUp(self):
self.client = Mock(ConcreteClient)
def test_calculate(self):
patch.object(ConcreteClient, 'get_some_basic_data',
return_value=my_fake_data).start()
result = self.client.calculate(42)
但它并不像我想象的那样起作用。。正如我所想,self.get_some_basic_data(param)
从my_fake_data
函数返回我的列表,但它看起来仍然是一个模拟对象,这对我来说是不可能的
这里出了什么问题?您在这里面临两个主要问题。引起您当前问题的主要原因是您实际上是如何嘲笑的。现在,由于您实际上正在为ConcreteClient
修补对象
,因此您需要确保您仍在使用真正的ConcreteClient,但在测试时模拟要模拟的实例的属性。您实际上可以在文档中看到此插图。不幸的是,没有明确的锚定线,但如果您遵循以下链接:
该节规定:
在使用patch()为您创建模拟的地方,您可以获得
使用with语句的“as”形式引用模拟:
参考代码为:
class ProductionClass:
def method(self):
pass
with patch.object(ProductionClass, 'method') as mock_method:
mock_method.return_value = None
real = ProductionClass()
real.method(1, 2, 3)
mock_method.assert_called_with(1, 2, 3)
这里需要注意的关键事项是如何调用所有内容。请注意,类的真实实例已创建。在您的示例中,执行此操作时:
self.client = Mock(ConcreteClient)
您正在创建一个在客户机上指定的Mock
对象。因此,最终这只是一个Mock
对象,它保存ConcreteClient
的属性。您实际上不会持有ConcreteClient
的真实实例
解决这个问题。只需在修补对象后创建一个真实实例。此外,为了使您的生活更轻松,您不必手动启动/停止patch.object,请使用上下文管理器,它将为您节省大量的麻烦
最后,第二个问题是返回值。您的return\u值
实际上是在返回未调用的my\u fake\u数据
函数。实际上,您需要数据本身,因此它需要是该函数的返回。您可以将数据本身作为返回值
考虑到这两个更正,您的测试现在应该如下所示:
class ConcreteClientTest(unittest.TestCase):
def test_calculate(self):
with patch.object(ConcreteClient, 'get_some_basic_data',
return_value=[{"key1": "val1"}, {"key2": "val2"}]):
concrete_client = ConcreteClient(Mock())
result = concrete_client.calculate()
self.assertEqual(
result,
[{"key1": "val1"}, {"key2": "val2"}]
)
我冒昧地返回了计算中的获取一些基本数据的结果,只是为了比较一下。我不确定你真正的代码是什么样子的。但是,归根结底,你的测试结构,你应该如何做这一点,是说明了以上