Skip to content Skip to sidebar Skip to footer

Mocking File Reads Using Patch Decorator And Side_effect

I am testing a function that reads a file, does operations to the contents and returns a value depending on what it sees. The function testme I test lives in module.py. I am runnin

Solution 1:

I would consider the following:

from io import TextIOWrapper, BytesIO
from unittest.mock import patch, mock_open

defopen_file(filename):
    withopen(filename, 'r') as f:
        data = f.readline()
    return data

defstring_byte_me(input):
    return TextIOWrapper(BytesIO(input))

defside_effect(filename, mode):
    if filename == 'correct':
        return string_byte_me(b'1 2 3')
    else:
        return string_byte_me(b'a b c')

m = mock_open()
m.side_effect = side_effect
@patch('builtins.open', m)deftest_open_file():
    assert open_file('correct') == '1 2 3'assert open_file('incorrect') == 'a b c'
test_open_file() # Passes.

This works by adding side_effect to the mock_open object after instantiation (not sure if there is a better way?). The returned side_effect must be capable of .readline() hence the TextIOWrapper.

Solution 2:

As I stated in a previous comment : I'm not sure about that since you didn't include any occurence of a test_testme function in the code you gave us. However if it is the module.testme method you are using, you forgot to declare the string parameter in the method definition. Depending on your feedback, I might make this an answer.

Edit : I wasn't exactly on the spot, as the argument your forgot was rather the self.

Apparently, this worked for you, so here is the promised answer.

Assuming the module.testme method you talked about is a function looking like :

TestTestMe(unittest.TestCase):
...
deftestme(filepath):
withopen(filepath, 'r') as f:
    line = f.readline().strip().split()
returnint(line[2])

This function, however, is rather a method, as you are accessing it from an object. (doing module.testme('foo')), and as such, the first argument given to the call will always be the implicit self.

So what happens is, you have your function expecting one argument, a string ('foo'), but two are given even if self isn't explicit : '(self, 'foo')'.

Thus the error, which says you receive more arguments than you ask for. The correction is quite simple : add self to the expected arguments of testme.

Which would then become:

deftestme(self, filepath):
    withopen(filepath, 'r') as f:
        line = f.readline().strip().split()
    returnint(line[2])

Hope this helped. Errors concerning amount of arguments are really often due to this kind of forgotten details. Although you don't need the self, it will always be passed as first positional argument (in python).

Have a nice day ! PS: Sorry for some strange english phrasing and repetitions.

Post a Comment for "Mocking File Reads Using Patch Decorator And Side_effect"