Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

I'm using mock with py.test for unittests.

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. For preprocess, I use side_effect to configure multiple return values, one for each of the rows.

How do I assert that the second argument passed to batch_process is a generator expression of preprocessed rows?

like image 457
satoru Avatar asked Dec 22 '25 03:12

satoru


1 Answers

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.

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. 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.

like image 169
Michele d'Amico Avatar answered Dec 23 '25 16:12

Michele d'Amico



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!