Reputation: 4592
I have a function that looks like this:
def run_shell_command_return_output(command_array):
output = []
p = Popen(command_array, stdout=PIPE, bufsize=1)
with p.stdout:
for line in iter(p.stdout.readline, b''):
output.append(line.decode('utf8').strip())
p.wait()
return output
I'm trying to figure out how to unit test code that uses this method so that it doesn't actually hit the filesystem but instead uses fake return data and status codes.
I've seen information on how to mock code that uses popen with communicate(), such as How to unit test a function that uses Popen?, but I haven't been able to figure out how to mock code using popen in this manner.
How can I fake out popen here so that this method can return fake output?
Upvotes: 0
Views: 1291
Reputation: 532133
First, I'd rewrite the function more simply. In particular, the with
statement is unnecessary, since you are neither opening (nor responsible for closing) p.stdout
.
def run_shell_command_return_output(command_array):
output = []
p = Popen(command_array, stdout=PIPE, bufsize=1)
for line in p.stdout:
output.append(line.decode('utf8').strip())
# I think the wait is redundant, since reads on p.stdout
# would block if p is still running.
p.wait()
return output
Now to test, you just mock Popen
and configure p.stdout
to be a file-like object with the desired data.
with mock.patch('Popen') as mock_popen:
mock_popen.return_value.stdout = io.StringIO("data\ndata\ndata\n")
output = run_shell_command_return_output(["what", "ever"])
assert output == ["data", "data", "data"]
Upvotes: 2