2015-03-25 4 views
1


У меня есть класс, представляющий наш DB слой, который будучи инстанцированный внутри в некоторых классах (я не могу передать его в качестве внешнего параметра)
Например:
Возможно ли исправление экземпляра класса с помощью существующего экземпляра Singleton?

class MyClass(object): 
    def __init__(self): 
     self.dbapi = DatabaseAPI() 
     self.timeout = 120 

    def some_methods(self): 
     pass 

Мы пишем несколько тестов Unit , и мы хотели бы высмеять 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 создается с реальным объектом, а не с предварительно сделанной издеваться ,

Что мне не хватает?
BTW, мы запускаем python 2.7

Заранее благодарен!

+0

Можете ли вы объяснить, как вы импортировать '' DatabaseAPI' в MyModule'? –

+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 
+0

HI Daniel, Спасибо за быстрый ответ. Я виноват, что я «пропустил» эту часть, но в своем коде я фактически исправляю полный путь класса, включая модули. Я обновлю вопрос –

+0

Что касается вашей второй рекомендации, У нас есть несколько сотен классов, написанных аналогично MyClass. Я пытаюсь создать один декоратор патча, который подойдет всем им без необходимости создавать другой патч для каждого теста (по мере изменения имени класса). Кроме того, я бы предпочел не менять код этих классов, если не будет другого способа. –

0

Короткий ответ: используйте

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

вместо этого.

В MyModuleDatabaseAPI что-то вроде фабрики, но my_dbapi - это пример. Поэтому, задав экземпляр как возвращаемое значение вашего завода, вы издеваетесь над ссылкой self.dbapi.

Если в производственном коде вы можете изменить дизайн, немного подумайте о том, чтобы двигаться, как это предлагает @ DanielRoseman: это лучший дизайн.

Смежные вопросы