简体   繁体   English

如何断言用生成器调用了模拟函数?

[英]How to assert that a mock function is called with a generator?

I'm using mock with py.test for unittests. 我正在将py.testmock一起用于单元测试。

One function under test looks like the one below: 被测试的一项功能如下所示:

def convert(rows):
    rows = (preprocess(r) for r in rows)
    return batch_process(True, rows)

In the test, I would mock preprocess and batch_process . 在测试中,我将模拟preprocessbatch_process For preprocess , I use side_effect to configure multiple return values, one for each of the rows. 对于preprocess ,我使用side_effect来配置多个返回值,每行一个。

How do I assert that the second argument passed to batch_process is a generator expression of preprocess ed rows? 我如何断言传递给batch_process的第二个参数是preprocess行的生成器表达式?

Consider to simplify your test: what you need to test is that the second argument when is traversed as a generator contains the values returned by preprocess() for each row. 考虑简化测试:您需要测试的是,作为生成器遍历时的第二个参数包含每行的preprocess()返回的值。

I will just sketch how I can eventually write it : 我将概述如何最终编写它:

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

Sure, in that way you don't check strictly it is a generator, but you check convert() behavior. 当然,您不必严格检查它是否是生成器,但可以检查convert()行为。 Check exactly how you have implemented it (by generator or by list) is not what a test should do, it is an implementation detail and not a behavior: you should write the best test that works in both cases. 确切地检查您是如何实现的(不是按生成器还是按列表)不是测试应该做什么,它是实现的细节而不是行为:您应该编写在两种情况下都可以使用的最佳测试。

I've found a way to check this, but it is little verbose, but works for me in my project 我已经找到一种检查方法,但是它有点冗长,但是在我的项目中对我有用

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]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM