是否可以使用现有的Singleton实例修补类实例?

时间:2015-03-25 12:48:53

标签: python unit-testing nose nosetests python-unittest


我有一个表示我们的DB层的类,它在某些类中被内部实例化(我不能将它作为外部参数传递)
例如:

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

提前致谢!

2 个答案:

答案 0 :(得分:2)

你正在修补错误的东西。您需要在分配属性的模块中进行修补,即包含目标类的模块。

如果在目标类中定义了一个获取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

答案 1 :(得分:0)

简短回答:使用

@patch('MyModule.DatabaseAPI', return_value=my_dbapi)

代替。

MyModule DatabaseAPI就像工厂一样,但my_dbapi是一个实例。因此,通过将实例设置为工厂的返回值,您可以模拟self.dbapi引用。

如果在生产代码中你可以改变设计,可以考虑移动@ DanielRoseman的答案:这是一个更好的设计。