Liondancer
Liondancer

Reputation: 16469

Mocking subprocess.check_call more than once

I have a function that calls subprocess.check_call() twice. I want to test all their possible outputs. I want to be able to set the first check_call() to return 1 and the second to return 0 and to do so for all possible combinations. The below is what I have so far. I am not sure how to adjust the expected return value

@patch('subprocess.check_call')
def test_hdfs_dir_func(mock_check_call):
    for p, d in list(itertools.product([1, 0], repeat=2)):
        if p or d:

Upvotes: 0

Views: 732

Answers (1)

wholevinski
wholevinski

Reputation: 3828

You can assign the side_effect of your mock to an iterable and that will return the next value in the iterable each time it's called. In this case, you could do something like this:

import copy
import itertools
import subprocess

from unittest.mock import patch

@patch('subprocess.check_call')
def test_hdfs_dir_func(mock_check_call):
    return_values = itertools.product([0, 1], repeat=2)
    # Flatten the list; only one return value per call
    mock_check_call.side_effect = itertools.chain.from_iterable(copy.copy(return_values))
    for p, d in return_values:
        assert p == subprocess.check_call()
        assert d == subprocess.check_call()

Note a few things:

  • I don't have your original functions so I put my own calls to check_call in the loop.
  • I'm using copy on the original itertools.product return value because if I don't, it uses the original iterator. This exhausts that original iterator when what we want is 2 separate lists: one for the mock's side_effect and one for you to loop through in your test.
  • You can do other neat stuff with side_effect, not just raise. As shown above, you can change the return value for multiple calls: https://docs.python.org/3/library/unittest.mock-examples.html#side-effect-functions-and-iterables
    • Not only that, but you can see from the link above that you can also give it a function pointer. That allows you to do even more complex logic when keeping track of multiple mock calls.

Upvotes: 1

Related Questions