ユニットテストに2つの他の関数の呼び出しを含む関数があります。パッチを使用して、両方の機能を同時に適切にモックする方法はわかりません。以下に私が意味することの例を示しました。 nosetestsを実行すると、テストはパスしますが、これを行うにはよりクリーンな方法が必要だと感じ、f.close()に関する部分を実際に理解していません...
ディレクトリ構造は次のようになります。
program/
program/
data.py
tests/
data_test.py
data.py:
import cPickle
def write_out(file_path, data):
f = open(file_path, 'wb')
cPickle.dump(data, f)
f.close()
data_test.py:
from mock import MagicMock, patch
def test_write_out():
path = '~/collection'
mock_open = MagicMock()
mock_pickle = MagicMock()
f_mock = MagicMock()
with patch('__builtin__.open', mock_open):
f = mock_open.return_value
f.method.return_value = path
with patch('cPickle.dump', mock_pickle):
write_out(path, 'data')
mock_open.assert_called_once_with('~/collection', 'wb')
f.close.assert_any_call()
mock_pickle.assert_called_once_with('data', f)
結果:
$ nosetests
.
----------------------------------------------------------------------
Ran 1 test in 0.008s
OK
パッチデコレータを使用し、次のようにネストすることでテストを簡素化できます(デフォルトではMagicMock
オブジェクトです)。
_@patch('cPickle.dump')
@patch('__builtin__.open')
def test_write_out(mock_open, mock_pickle):
path = '~/collection'
f = mock_open.return_value
f.method.return_value = path
write_out(path, 'data')
mock_open.assert_called_once_with('~/collection', 'wb')
mock_pickle.assert_called_once_with('data', f)
f.close.assert_any_call()
_
MagicMock
インスタンスを呼び出すと、新しいMagicMock
インスタンスが返されるため、返された値が他の模擬オブジェクトと同じように呼び出されたことを確認できます。この場合、f
は'open()'
という名前のMagicMock
です(f
を印刷してみてください)。
応答@Matti Johnに加えて、関数test_write_out
内でpatch
を使用することもできます。
from mock import MagicMock, patch
def test_write_out():
path = '~/collection'
with patch('__builtin__.open') as mock_open, \
patch('cPickle.dump') as mock_pickle:
f = mock_open.return_value
...
モックを使用してcreate_collection
関数でConflictError
のレイズをテストする方法の簡単な例を次に示します。
import os
from unittest import TestCase
from mock import patch
from ..program.data import ConflictError, create_collection
class TestCreateCollection(TestCase):
def test_path_exists(self):
with patch.object(os.path, 'exists') as mock_method:
mock_method.return_value = True
self.assertRaises(ConflictError, create_collection, 'test')