如何断言生成器调用了模拟函数?
How to assert that a mock function is called with a generator?
我正在使用 mock
和 py.test
进行单元测试。
一个被测函数如下所示:
def convert(rows):
rows = (preprocess(r) for r in rows)
return batch_process(True, rows)
在测试中,我会模拟preprocess
和batch_process
。
对于 preprocess
,我使用 side_effect
配置多个 return 值,每一行一个。
如何断言传递给 batch_process
的第二个参数是 preprocess
ed 行的生成器表达式?
考虑简化您的测试:您需要测试的是作为生成器遍历的第二个参数 when 包含 preprocess()
为每一行返回的值。
我只是勾画一下我最终会如何写它:
from mock import Mock, call
preprocess_sentinels = [Mock() for _ in range(5)]
mock_preprocess.side_effect = preprocess_sentinels
rows = [Mock() for _ in range(5)]
convert(rows)
mock_preprocess.assert_has_calls([call(r) for r in rows])
args, kwargs = mock_batch_process.call_args
assert args[0]
for v, e in zip(args[1], preprocess_sentinels):
assert v == e
当然,这样您 不严格检查 它是一个生成器,但您检查 convert()
行为。确切地检查你是如何实现它的(通过生成器或通过列表)不是测试应该做的,它是一个实现细节而不是一种行为:你应该编写在这两种情况下都有效的最佳测试。
我找到了一种方法来检查这个,但它有点冗长,但在我的项目中对我有用
from mock import Mock, patch
from types import GeneratorType
def test():
mock_batch_process = patch('module.calling.batch_process')
mock_preprocess = patch('module.calling.preprocess')
# our test data for rows
rows = ...
convert(rows)
assert mock_batch_process.call_count == 1
args, kwargs = mock_batch_process.call_args
# get an arg that is expected to be a generator, second arg in this case
preprocess_rows = args[1]
# check that our call arg is a generator
assert isinstance(preprocess_rows, GeneratorType)
# check that it contains all expected values
assert list(preprocess_rows) == [mock_preprocess(row) for row in rows]
我正在使用 mock
和 py.test
进行单元测试。
一个被测函数如下所示:
def convert(rows):
rows = (preprocess(r) for r in rows)
return batch_process(True, rows)
在测试中,我会模拟preprocess
和batch_process
。
对于 preprocess
,我使用 side_effect
配置多个 return 值,每一行一个。
如何断言传递给 batch_process
的第二个参数是 preprocess
ed 行的生成器表达式?
考虑简化您的测试:您需要测试的是作为生成器遍历的第二个参数 when 包含 preprocess()
为每一行返回的值。
我只是勾画一下我最终会如何写它:
from mock import Mock, call
preprocess_sentinels = [Mock() for _ in range(5)]
mock_preprocess.side_effect = preprocess_sentinels
rows = [Mock() for _ in range(5)]
convert(rows)
mock_preprocess.assert_has_calls([call(r) for r in rows])
args, kwargs = mock_batch_process.call_args
assert args[0]
for v, e in zip(args[1], preprocess_sentinels):
assert v == e
当然,这样您 不严格检查 它是一个生成器,但您检查 convert()
行为。确切地检查你是如何实现它的(通过生成器或通过列表)不是测试应该做的,它是一个实现细节而不是一种行为:你应该编写在这两种情况下都有效的最佳测试。
我找到了一种方法来检查这个,但它有点冗长,但在我的项目中对我有用
from mock import Mock, patch
from types import GeneratorType
def test():
mock_batch_process = patch('module.calling.batch_process')
mock_preprocess = patch('module.calling.preprocess')
# our test data for rows
rows = ...
convert(rows)
assert mock_batch_process.call_count == 1
args, kwargs = mock_batch_process.call_args
# get an arg that is expected to be a generator, second arg in this case
preprocess_rows = args[1]
# check that our call arg is a generator
assert isinstance(preprocess_rows, GeneratorType)
# check that it contains all expected values
assert list(preprocess_rows) == [mock_preprocess(row) for row in rows]