Can mock.mock_open.read return different values?
Tim Golden
mail at timgolden.me.uk
Mon Mar 12 04:51:32 EDT 2018
I'm contributing to a codebase which makes heavy use of mock in the test
suite, a technique which I'm aware of but have used only rarely. In one
situation it uses mock.mock_open(read_data="...") and then asserts again
mock_open.return_value.read.call_count.
A code change I've made results in an increase in the call count but
also the open() I've introduced opens the file in binary mode and does
something with the resulting data.
Hugely simplified, the new code and unchanged test looks like this:
import os, sys
import unittest
from unittest import mock
def read_file(filename):
#
# This section is new
#
with open(filename, "rb") as f:
text = f.read()
if text.startswith(b"#"):
pass
with open(filename) as f:
text = f.read()
if text.startswith("#"):
pass
return text
class TestS(unittest.TestCase):
def test_read_file(self):
mock_open = mock.mock_open(read_data="abc")
with mock.patch('builtins.open', mock_open):
data = read_file("abc")
assert mock_open.return_value.read.call_count == 1
if __name__ == '__main__':
unittest.main()
I would expect the test to fail because of the call_count change. But in
fact it errors out because the newly-added "if test.startswith()"
receives a string, not bytes, from the Mock's read_data functionality.
Ignore for the moment any question of changing the read_file
implementation to assist testing. And leave aside the question of
whether a mock_open is really a good test approach here.
Is there any way in which I can have the mock_open object return bytes
for the first open and a string for the second? I've looked at setting a
side_effect function against the mock_open.return_value.read Mock, but I
can't see a way of having the function know whether it's supposed to be
returning bytes or string.
TJG
More information about the Python-list
mailing list