#python #mocking #python-unittest
#python #издевательство #python-unittest
Вопрос:
Я пишу модульные тесты для функции, которая должна получать все допустимые вложения в сообщении электронной почты. Моя функция имеет следующее поведение:
def extract_attachments(local_file):
email_file = open(local_file, "r")
msg = email.message_from_file(email_file)
attchs = [x for x in msg.get_payload() if x.get_filename() is not None]
for attch in attchs:
filename = attch.get_filename()
if filename not in VALID_ATTACHMENTS:
raise Exception('Invalid attachment', filename)
return attchs
Как я могу заставить эту функцию возвращать некоторый объект с помощью функции get_filename()
?
Я пытаюсь это исправить, но получаю сообщение об ошибке 'list' object has no attribute 'get_payload'
.
@patch("mail_extractor.process_email.email")
@patch("builtins.open")
def test_extract_attachments(open, email):
email.message_from_file.return_value = []
email.get_payload.return_value = ['1.xml']
result = process_email.extract_attachments('mock')
assert len(result) == 1
Ответ №1:
Описанная вами нотация специфична для объектов, и то, что вы пытаетесь ей придать, — это метод. Вам нужно будет определить класс:
class MyClass:
def get_filename():
# some logic
Затем вы сможете создать экземпляр вашего объекта:
x = MyClass()
x.get_filename()
Это отвечает на ваш вопрос?
Комментарии:
1. Итак, мне нужно написать класс для макета методов электронной почты?
2. Я думаю, что на самом деле вы намеревались сделать вот что:
attchs = [msg for x in msg.get_payload() if msg.get_filename() is not None]
таким образом, у вас все еще будут объекты msg, просто отфильтрованные по результатамget_filename
. Я предполагаю, чтоget_payload()
возвращает список, а не объект.3. Я понял это. Позвольте мне попробовать одну вещь
Ответ №2:
Способ, которым вы настроили свои mocks, не совсем правильный. message_from_file()
Вызов должен вернуть сообщение, в то время как вы возвращаете список — отсюда и ошибка, которую вы видите.
Вы должны настроить макет сообщения вместе с макетом вложения, чтобы удовлетворять вызовам, которые ожидает выполнить код.
Например:
@patch("mail_extractor.process_email.email")
@patch("builtins.open")
def test_extract_attachments(open, email):
# Configure the mock message and its attachment
mock_message = Mock()
mock_attachment = Mock()
mock_attachment.get_filename.return_value = '1.xml'
mock_message.get_payload.return_value = [mock_attachment]
# Configure message_from_file to return the mock message
email.message_from_file.return_value = mock_message
result = process_email.extract_attachments('mock')
assert len(result) == 1