94

単体テストしたい関数には、他の 2 つの関数の呼び出しが含まれています。パッチを使用して両方の機能を同時に適切にモックする方法がわかりません。以下に、私が意味することの例を示しました。私がノーズテストを実行すると、テストはパスしますが、これを行うためのよりクリーンな方法が必要であると感じており、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
4

3 に答える 3

136

patch デコレータを使用してネストすることで、テストを簡素化できます (MagicMockデフォルトではオブジェクトです)。

from unittest.mock import patch

@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インスタンスが返されるため、返された値が他のモック オブジェクトと同じように呼び出されたことを確認できます。この場合fMagicMock名前付きです'open()'(印刷してみてくださいf)。

于 2013-04-10T09:47:39.613 に答える
72

応答 @Matti John に加えて、patch関数内で使用することもできtest_write_outます。

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
        ...
于 2015-06-12T08:55:13.420 に答える
2

モックを使用して関数ConflictError内でレイズをテストする方法の簡単な例を次に示します。create_collection

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')

mock docsと Michael Foord の素晴らしいmock の紹介も参照してください。

于 2013-04-06T19:13:38.227 に答える