Changing function arguments and have tests pass because the function was mocked

Recently I changed a function to receive a single argument instead of the previous two. Unfortunately that resulted in another function failing later. The issue wasn’t lack of tests (that function had 100% coverage), but the way this function was tested.

@patch('module.function_changed')
def test_that_function_was_called(mock_function):
    task()
    mock_function.assert_called_with('arg1', 'arg2')

One of the downsides of using mock objects in tests is that you lose the connection to the original object. So the code above runs happily and the test passes because mock_function is a simple Mock object. But we don’t need to accept this, a simple change will make the Mock object validate that the arguments are valid for the original functional:

@patch('module.function_changed', autospec=True)
def test_that_function_was_called(mock_function):
    task()
    mock_function.assert_called_with('arg1', 'arg2')

By adding autospec=True to the patch call, the arguments are validated against the original function signature, and in this case the call would raise a TypeError: function_changed() takes 1 positional argument but 2 were given and the test would fail. And now you’d know that something was wrong well before it gets deployed…

Want to get python/AWS tips on your email? Just subscribe!

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax