是否可以用现有的 Singleton 实例修补 class 实例?
Is it possible to patch a class instance with an existing Singleton instance?
我有一个 class 代表我们的数据库层,它在一些 classes 内部实例化(我不能将它作为外部参数传递)
例如:
class MyClass(object):
def __init__(self):
self.dbapi = DatabaseAPI()
self.timeout = 120
def some_methods(self):
pass
我们正在编写一些单元测试,我们想使用我们将在测试运行之前创建的现有实例来模拟 self.dbapi。
例如:
my_dbapi = DatabaseAPIMock()
...
...
@patch('MyModule.DatabaseAPI', my_dbapi)
def my_test(self):
my_class = MyClass() #<---This is where I'm not able to mock the DatabaseAPI
到目前为止,这是我试图实现的目标,但通过调试代码,我发现 self.dbapi 是用真实对象而不是预制模拟对象实例化的。
我错过了什么?
顺便说一句,我们是 运行 python 2.7
提前致谢!
简答:使用
@patch('MyModule.DatabaseAPI', return_value=my_dbapi)
相反。
在 MyModule
中 DatabaseAPI
类似于工厂,但 my_dbapi
是一个实例。因此,通过将实例设置为工厂的 return 值,您可以模拟 self.dbapi
引用。
如果在生产代码中您可以稍微更改设计,请考虑按照@DanielRoseman 的回答建议移动:这是一个更好的设计。
你打错了补丁。您需要在分配属性的模块中打补丁,即包含目标 class.
的模块
如果您在目标 class 中定义了一个方法来获取您的 DatabaseAPI 对象,那就更容易了。这样你就可以更容易地修补它。
class MyClass(object):
def __init__(self):
self.dbapi = self.get_db_api()
self.timeout = 120
def get_db_api():
return DatabaseAPI()
测试变为:
@patch('my_module.MyClass.get_db_api')
def my_test(self, my_method):
my_method.return_value = my_dbapi
我有一个 class 代表我们的数据库层,它在一些 classes 内部实例化(我不能将它作为外部参数传递)
例如:
class MyClass(object):
def __init__(self):
self.dbapi = DatabaseAPI()
self.timeout = 120
def some_methods(self):
pass
我们正在编写一些单元测试,我们想使用我们将在测试运行之前创建的现有实例来模拟 self.dbapi。
例如:
my_dbapi = DatabaseAPIMock()
...
...
@patch('MyModule.DatabaseAPI', my_dbapi)
def my_test(self):
my_class = MyClass() #<---This is where I'm not able to mock the DatabaseAPI
到目前为止,这是我试图实现的目标,但通过调试代码,我发现 self.dbapi 是用真实对象而不是预制模拟对象实例化的。
我错过了什么?
顺便说一句,我们是 运行 python 2.7
提前致谢!
简答:使用
@patch('MyModule.DatabaseAPI', return_value=my_dbapi)
相反。
在 MyModule
中 DatabaseAPI
类似于工厂,但 my_dbapi
是一个实例。因此,通过将实例设置为工厂的 return 值,您可以模拟 self.dbapi
引用。
如果在生产代码中您可以稍微更改设计,请考虑按照@DanielRoseman 的回答建议移动:这是一个更好的设计。
你打错了补丁。您需要在分配属性的模块中打补丁,即包含目标 class.
的模块如果您在目标 class 中定义了一个方法来获取您的 DatabaseAPI 对象,那就更容易了。这样你就可以更容易地修补它。
class MyClass(object):
def __init__(self):
self.dbapi = self.get_db_api()
self.timeout = 120
def get_db_api():
return DatabaseAPI()
测试变为:
@patch('my_module.MyClass.get_db_api')
def my_test(self, my_method):
my_method.return_value = my_dbapi