Исправление объекта по ссылке, а не по имени строки? - PullRequest
2 голосов
/ 13 февраля 2020

Наиболее распространенным способом исправления чего-либо в модуле, по-видимому, является использование чего-то вроде

from unittest.mock import patch

from mypackage.my_module.my_submodule import function_to_test

@patch('mypackage.my_module.my_submodule.fits.open')
def test_something(self, mock_fits_open)
    # ...
    mock_fits_open.return_value = some_return_value
    function_to_test()
    # ...

Однако, поскольку значение, передаваемое декоратору исправления, является строкой, я не получаю много приятные преимущества от IDE. Я не могу использовать части строки, чтобы перейти к определениям. Я не получаю автозаполнение (и неявную проверку орфографии). Ни полных возможностей рефакторинга. И так далее.

Используя patch.object, я могу приблизиться к тому, что ищу.

from unittest.mock import patch

import mypackage.my_module.my_submodule
from mypackage.my_module.my_submodule import function_to_test

@patch.object(mypackage.my_module.my_submodule.fits, 'open')
def test_something(self, mock_fits_open)
    # ...
    mock_fits_open.return_value = some_return_value
    function_to_test()
    # ...

Однако для этого все же требуется заключительная часть имени, на которое делается ссылка Объект - это просто строка. Есть ли (хороший) способ исправления объекта исключительно по ссылке на этот объект? То есть я хотел бы иметь возможность сделать что-то вроде

from unittest.mock import patch

import mypackage.my_module.my_submodule
from mypackage.my_module.my_submodule import function_to_test

@patch.reference(mypackage.my_module.my_submodule.fits.open)
def test_something(self, mock_fits_open)
    # ...
    mock_fits_open.return_value = some_return_value
    function_to_test()
    # ...

1 Ответ

2 голосов
/ 13 февраля 2020

Исправление работает путем замены в пространстве имен, в котором ищется имя .

Базовые логики c из mock.patch по существу работают с управляемым контекстом затенение имени . Вы можете сделать то же самое вручную:

  • сохранить исходное значение, связанное с именем (если есть)
  • try с перезаписью имени
  • выполнить код в test
  • finally возврат имени к исходному значению

Следовательно, вам принципиально необходимо выполнить патч для name , нет прямой ссылки на патч .

...