PicklingError при использовании макета для проверки вызывается функция

У меня возникли проблемы с проверкой того, что метод вызывается с использованием mock -- в качестве простого примера предположим, что метод os.getcwd. Я хочу проверить, что моя собственная функция pickle_wdir вызывает os.getcwd, как и предполагалось. Однако функция, которую я тестирую, обрабатывает значение, возвращаемое os.getcwd, что приводит к ошибке.

Вот простой пример для воспроизведения ошибки.

os_ex.py:

import os
import pickle

def pickle_wdir(filename):
    dir = os.getcwd()
    with open(filename, 'wb') as handle:
        pickle.dump(dir, handle)

test_os_ex.py:

from unittest import TestCase
from unittest.mock import patch
from os_ex import pickle_wdir


class TestPickleWdir(TestCase):
    def test_os_called(self):
        fname = 'dir.pickle'
        with patch('os_ex.os') as mocked_obj:
            pickle_wdir(fname)
            mocked_obj.getcwd.assert_called()

Возвращаемое сообщение об ошибке

_pickle.PicklingError: Can't pickle <class 'unittest.mock.MagicMock'>: it's not the same object as unittest.mock.MagicMock.

Как я могу проверить, что os.getcwd вызывается, не получая этого PicklingError?


person Dan McCabe    schedule 11.03.2020    source источник


Ответы (1)


Вам нужно смоделировать методы os.getcwd(), open() и pickle.dump(). Вы можете использовать unittest.mock.patch как менеджер контекста, чтобы сделать это.

E.g.

os_ex.py:

import os
import pickle


def pickle_wdir(filename):
    dir = os.getcwd()
    with open(filename, 'wb') as handle:
        pickle.dump(dir, handle)

test_os_ex.py:

import unittest
from unittest.mock import patch, mock_open
from os_ex import pickle_wdir


class TestOsEx(unittest.TestCase):
    def test_pickle_wdir(self):
        fname = 'dir.pickle'
        m = mock_open(read_data='mocked data')
        with patch('os_ex.os') as mocked_obj, patch('builtins.open', m) as mocked_open, patch('pickle.dump') as mocked_dump:
            mocked_obj.getcwd.return_value = '/root'
            pickle_wdir(fname)
            mocked_obj.getcwd.assert_called()
            m.assert_called_with(fname, 'wb')
            handle = mocked_open()
            mocked_dump.assert_called_with('/root', handle)


if __name__ == '__main__':
    unittest.main()

результаты модульного теста со 100% покрытием:

.
----------------------------------------------------------------------
Ran 1 test in 0.012s

OK
Name                                       Stmts   Miss  Cover   Missing
------------------------------------------------------------------------
src/stackoverflow/60627827/os_ex.py            6      0   100%
src/stackoverflow/60627827/test_os_ex.py      17      0   100%
------------------------------------------------------------------------
TOTAL                                         23      0   100%
person slideshowp2    schedule 27.04.2020