объект «модуль» не может быть вызван с помощью макетных модулей

#python #unit-testing #module #mocking #python-import

Вопрос:

Я пишу модульный тест для некоторого кода, и в коде, который я не могу изменить, есть этот вызов:

 aps = firebase_admin.messaging.Aps(  alert=None,  content_available=True,  sound="default",  custom_data={  "title": title,  "body": message,  "notification_id": notification_id,  "action_key": action_key  } )  

Я не хочу, чтобы что-то действительно происходило на стороне Firebase во время теста, но мне нужно убедиться, что блок кода, в котором находится этот вызов, будет выполнен. Поэтому я высмеял этот модуль вместе с некоторыми другими в своих файлах модульного тестирования:

 firebase_admin_module = __import__('tests.mock_firebase_admin') sys.modules['firebase_admin'] = firebase_admin_module sys.modules['firebase_admin.credentials'] = __import__('tests.mock_firebase_admin.credentials') setattr(firebase_admin_module, 'credentials', __import__('tests.mock_firebase_admin.credentials')) sys.modules['firebase_admin.messaging'] = __import__('tests.mock_firebase_admin.messaging') setattr(firebase_admin_module, 'messaging', __import__('tests.mock_firebase_admin.messaging')) sys.modules['firebase_admin._apps'] = __import__('tests.mock_firebase_admin._apps') setattr(firebase_admin_module, '_apps', __import__('tests.mock_firebase_admin._apps')) sys.modules['firebase_admin.messaging.Aps'] = __import__('tests.mock_firebase_admin.aps') setattr(firebase_admin_module.messaging, 'Aps', __import__('tests.mock_firebase_admin.aps'))  

Вот содержимое моего каталога mock_firebase_admin:

 $ tree mock_firebase_admin mock_firebase_admin ├── __init__.py # empty file ├── _apps.py ├── aps.py # Aps class is defined here ├── credentials.py ├── firebase_singleton.py └── messaging.py # The same Aps class is also defined here  

Вот мой макет класса Aps:

 class Aps():    def __init__(self, alert=None, content_available=True, sound="default", custom_data={}):  print("In Aps consturctor")  return {}  

Проблема в том, что вызов firebase_admin.messaging.Aps(...) завершается ошибкой с этой ошибкой:

 'module' object is not callable  

Что я пробовал до сих пор:

Замена Aps() класса Aps(...) функцией в обоих файлах выглядит следующим образом:

 def Aps(self, alert=None, content_available=True, sound="default", custom_data={}): print("In Aps function") pass  

That changed nothing, the same error persists.

Commenting out the line sys.modules['firebase_admin.messaging.Aps'] = __import__('tests.mock_firebase_admin.aps') . Changes nothing, the same error persists.

Commenting out the line setattr(firebase_admin_module.messaging, 'Aps', __import__('tests.mock_firebase_admin.aps')) . Then the error changes to 'module' object has no attribute 'Aps' .

Changing the line setattr(firebase_admin_module.messaging, 'Aps', __import__('tests.mock_firebase_admin.aps')) to setattr(firebase_admin_module.messaging, 'Aps', __import__('tests.mock_firebase_admin.aps.Aps')) . Results in the following traceback:

 ... tests/utils.py:28: in lt;modulegt;  setattr(firebase_admin_module.messaging, 'Aps', __import__('tests.mock_firebase_admin.aps.Aps')) E ImportError: No module named Aps  

Что я делаю не так? Как я могу исправить это так, чтобы вызов firebase_admin.messaging.Aps(...) вызывал класс в моем макетном модуле, а не сам модуль?