3

2 つのファイルを開き、それぞれに異なるデータを書き込むメソッドをテストする必要があります。ファイルがどの順序で書き込まれるかは問題ではありません。

モックを使用してopen.

from io import BytesIO
import mock

class MemorisingBytesIO(BytesIO):
    """Like a BytesIO, but it remembers what its value was when it was closed."""
    def close(self):
        self.final_value = self.getvalue()
        super(MemorisingBytesIO, self).close()

open_mock = mock.Mock()
open_mock.return_value = MemorisingBytesIO()

with mock.patch('__builtin__.open', open_mock):
    write_to_the_file()  # the function under test

open_mock.assert_called_once_with('the/file.name', 'wb')
assert open_mock.return_value.final_value == b'the data'

2 つのファイルに書き込むメソッドで動作するようにこのアプローチを変更するのに問題があります。side_effect2 つの s を連続して返すためにを使用MemorisingBytesIOし、それぞれに正しいデータが含まれていることを確認することを検討しましたが、その場合、テストは脆弱になります。メソッド内の呼び出しの順序が変更されると、テストは失敗します。

したがって、私が本当にやりたいことは、あるファイル名で呼び出されたときにopen_mock1 つを返しMemorisingBytesIO、別のファイル名で呼び出されたときに別のファイルを返すことです。私は他の言語のモッキ​​ングライブラリでこれを見てきました.サブクラス化せずにPythonで可能Mockですか?

4

2 に答える 2

1

次のアプローチはどうですか?(クラス属性を使用してファイルの内容を保持します):

from io import BytesIO
import mock

class MemorisingBytesIO(BytesIO):
    """Like a BytesIO, but it remembers what its value was when it was closed."""
    contents = {}
    def __init__(self, filepath, *args, **kwargs):
        self.filepath = filepath
        super(MemorisingBytesIO, self).__init__()
    def close(self):
        self.contents[self.filepath] = self.getvalue()
        super(MemorisingBytesIO, self).close()

def write_to_the_file():
    with open('a/b.txt', 'wb') as f:
        f.write('the data')
    with open('a/c.txt', 'wb') as f:
        f.write('another data')


#MemorisingBytesIO.contents.clear()
open_mock = mock.Mock(side_effect=MemorisingBytesIO)
with mock.patch('__builtin__.open', open_mock):
    write_to_the_file()  # the function under test

open_mock.assert_called_once_with('a/b.txt', 'wb')
open_mock.assert_called_once_with('a/c.txt', 'wb')
assert MemorisingBytesIO.contents['a/b.txt'] == b'the data'
assert MemorisingBytesIO.contents['a/c.txt'] == b'another data'
于 2013-08-25T12:39:23.327 に答える
0

それ以来、私が最初に を使用してやりたかったことを行う方法を発見しましたmockside_effect関数に equal を設定できます。モックが呼び出されると、その関数に引数が渡されます。

In [1]: import mock

In [2]: def print_it(a, b):
   ...:     print b
   ...:     print a
   ...:     

In [3]: m = mock.Mock(side_effect=print_it)

In [4]: m('hello', 2)
2
hello

2 つのファイルを操作する元の例を次のように記述します。

fake_file_1 = MemorisingBytesIO()
fake_file_2 = MemorisingBytesIO()

def make_fake_file(filename, mode):
    if filename == 'a/b.txt':
        return fake_file_1
    elif filename == 'a/c.txt':
        return fake_file_2
    else:
        raise IOError('Wrong file name, Einstein')

open_mock = mock.Mock(side_effect=make_fake_file)
with mock.patch('__builtin__.open', open_mock):
    write_to_the_file()

assert ('a/b.txt', 'wb') in open_mock.call_args
assert ('a/c.txt', 'wb') in open_mock.call_args
assert fake_file_1.final_value == 'file 1 data'
assert fake_file_2.final_value == 'file 2 data'
于 2013-08-26T21:23:58.877 に答える