Pytest макет с использованием декоратора для макета функции, содержащей возвращаемое значение диспетчера контекста, не переданное

#python-3.x #unit-testing #mocking #pytest

#python-3.x #модульное тестирование #издевательство #pytest

Вопрос:

Итак, я борюсь с издевательством над этой функцией из-за диспетчера контекста.

Тестируемая функция

 import fitz

def with_test_func(next_pdfs_path):
    text = ''
    with fitz.open(next_pdfs_path) as doc:
        text = doc
    return text

 

Тестовый код

 @mock.patch("content_production.fitz.open.__enter__", return_value='value_out')
def test_with_test_func(mock_fitz_open):
    assert cp.with_test_func('value_in') == 'value_out'

 

Ошибка

 RuntimeError: cannot open value_in: No such file or directory
 

Я протестировал это без диспетчера контекста, и это работает. Итак, как мне это исправить? Спасибо

Редактировать

Итак, как было предложено @MrBean, я попробовал это

 @mock.patch("content_production.fitz.open.return_value.__enter__", return_value='value_out')
def test_with_test_func(mock_fitz_open):
    assert cp.with_test_func('value_in') == 'value_out'

 

Это выдает мне эту ошибку

 thing = <class 'fitz.fitz.Document'>, comp = 'return_value', import_path = 'content_production.fitz.open.return_value'

    def _dot_lookup(thing, comp, import_path):
        try:
            return getattr(thing, comp)
        except AttributeError:
>           __import__(import_path)
E           ModuleNotFoundError: No module named 'content_production.fitz'; 'content_production' is not a package

 

Комментарии:

1. Я думаю, вы забыли return_value , например content_production.fitz.open.return_value.__enter__ , получить результат open вызова.

2. Спасибо, я уже пробовал это, а также нравится это content_production.fitz.open.__enter__.return_value , и они не работают. С вашим предложением ошибка была ModuleNotFoundError: No module named 'content_production.fitz'; 'content_production' is not a package

3. Тестируется ли content_production модуль с вашей функцией и является ли он верхнего уровня?

4. Да, верхний уровень и да, это модуль с функцией. Как я уже сказал, это работало без context manager, поэтому я думаю, что меня сбивает с толку то, как работает context manager.

5. Извините, мой комментарий вводит в заблуждение — не заметил очевидного… Я вставил это в ответ.

Ответ №1:

Проблема в том, что это return_value свойство макета, а не исправленной функции, поэтому вы не можете поместить его в строку patch аргумента. Вместо этого вы должны установить возвращаемое значение в макете для open метода:

 @mock.patch("content_production.fitz.open")
def test_with_test_func(mock_fitz_open):
    mock_fitz_open.return_value.__enter__.return_value = 'value_out'
    assert cp.with_test_func('value_in') == 'value_out'