Python mocking: missing 1 required positional argument
Asked Answered
M

2

7

I'm writing tests for my Flask project, and are trying to mock my database model. The code looks something like this:

import unittest.mock

@unittest.mock.patch("server.models.user")
def test_that_response_contain_correct_user_data(self, mocked_user):

This results in this error message:

TypeError: test_that_response_contain_correct_user_data() missing 1 required positional argument: 'mocked_user'

So it looks like the mocking framwork doesn't inject the mocked data into the function. Does anyone know what may be causing this?

Marinemarinelli answered 19/9, 2018 at 11:16 Comment(3)
Is your test_that_response_contain_correct_user_data() a function (not belonging to any class) or a method (part of a class)? If it is a function, the first argument self gets the patch object, while the second argument is not provided (so the error message). In that case, remove self.Oakland
This didn't work for me. I am using @patch.object, though.Moor
Why is there a "self" argument in a module level function? The number of arguments need to match the number of patches applied here. If there's an enclosing class that you're not showing us, you'll need to update the example to include that detail.Bagworm
G
-3

You need to import patch from unittest.mock and use that decorator to inject the mocked data.

from unittest.mock import patch

@patch("server.models.user")
def test_that_response_contain_correct_user_data(self, mocked_user):
Glyptic answered 28/11, 2018 at 23:52 Comment(3)
So, the only difference between your code and the original code is that you use the from ... import ... form of import. How does it change anything?Motet
This does not work. Should be unmarked as answer.Unfurl
Who knows why this has any upvotes.Elenoraelenore
E
0

It turns out that you can't pass the self argument as it is not passed during the call but likely added later. So, to get it to work, I had to just hardcode a return value.

I had to change from this:

from unittest.mock import patch

from path.to.file import ClassName

@pytest.fixture
def mock_fn():
    with patch("path.to.file.ClassName.function_to_mock", wraps=ClassName.function_to_mock) as mocked_fn:
        yield mocked_fn

def test_function_to_mock(mock_fn):
    ...
    assert mock_fn.call_count == 2

To this:

...

@pytest.fixture
def mock_fn():
    with patch.object(ClassName, "function_to_mock") as mocked_fn:  # Just patch here
        yield mocked_fn

def test_function_to_mock(mock_fn):
    mock_fn.return_value = (False, 4, True, 1)  # And then hardcode return value
    ...
    assert mock_fn.call_count == 2
Elenoraelenore answered 30/4 at 20:26 Comment(0)
G
-3

You need to import patch from unittest.mock and use that decorator to inject the mocked data.

from unittest.mock import patch

@patch("server.models.user")
def test_that_response_contain_correct_user_data(self, mocked_user):
Glyptic answered 28/11, 2018 at 23:52 Comment(3)
So, the only difference between your code and the original code is that you use the from ... import ... form of import. How does it change anything?Motet
This does not work. Should be unmarked as answer.Unfurl
Who knows why this has any upvotes.Elenoraelenore

© 2022 - 2024 — McMap. All rights reserved.