Найти - Пользователи
Полная версия: Mock и импортируемые модули/функции
Начало » Python для экспертов » Mock и импортируемые модули/функции
1
Master_Sergius
Схематическое изложение (ибо всё секретно )
имеется модуль, который нужно протестировать - “master_module.py”:

# different imports, path patches, etc...
...
from clients import WebAPIClient
from utils.conf import config
 
class WebClient(object):
 
    def __init__(self):                                                         
           conf = config.get_config('web')                                        
           self.__client = WebAPIClient(host=conf['master_service.host'],\
                                                         user=conf['master_service.user'], \
                                                         password=conf['master_service.password'])
   ....
   # different methods
   ....

Суть в том, что не получается подсунуть “замокать” config.get_config(), чтобы он вернул нужный словарь. К примеру, если в юниттесте я сделаю так:

sys.modules['utils.conf'] = Mock()
 
from master_module import WebClient
 
config = Mock()
config.get_config = Mock(return_value={'master_service.host':'mock_host', 'master_service.user':'mock_user', 'corpus_api.password':'mock_pass'})
print config.get_config()

то он напечатает нужный словарь, но когда вызываю:

client = WebClient()

то этот замоканный config не передается, а передается лишь - sys.modules = Mock(), в итоге получаю:

Traceback .... bla-bla .... in __init__
    host=conf['master_service.host'], \
TypeError: 'Mock' object is unsubscriptable

Как решить данную проблему?


Сумел пропатчить вот таким способом:

import clients
globals()['clients'].config = config # assign mocked config

где config - это уже тот мой замоканный

Возможно, есть более элегантное решение? Или вообще другой подход к такому тестированию?
py.user.next
Master_Sergius
Возможно, есть более элегантное решение?
Надо патчить прямо в том модуле.
from utils.conf import config
Master_Sergius
py.user.next
Надо патчить прямо в том модуле.
from utils.conf import config

В смысле? Дописывать что-то в другой модуль? Не думаю, что это верное решение. Юниттесты никоим образом не должны влиять на модули.
py.user.next
Master_Sergius
В смысле? Дописывать что-то в другой модуль?
Не дописывать, а использовать patch().

>>> from unittest.mock import patch
>>> 
>>> p = patch('os.path.join')
>>> p.start()
<MagicMock name='join' id='3073445324'>
>>> 
>>> import os
>>> 
>>> os.path.join('x')
<MagicMock name='join()' id='3073462732'>
>>> 
>>> p.stop()
>>>

Пример
t.py
#!/usr/bin/env python3
 
import os
 
def main():
    print('hello')
    print(os.path.join('x', 'y'))
 
if __name__ == '__main__':
    main()

u.py
#!/usr/bin/env python3
 
from unittest.mock import patch
import t
 
p = patch('os.path.join')
p.start()
 
t.main()
 
p.stop()

Вывод
[guest@localhost py]$ ./t.py 
hello
x/y
[guest@localhost py]$ ./u.py
hello
<MagicMock name='join()' id='3073278892'>
[guest@localhost py]$
This is a "lo-fi" version of our main content. To view the full version with more information, formatting and images, please click here.
Powered by DjangoBB