The standard way to do this kind of test is to mock the entire class, like so:
def test_bar(mocker):
mock_foo = mocker.MagicMock(name='Foo')
mocker.patch('test.Foo', new=mock_foo)
mock_foo.return_value.x = 2
assert bar() == 3
mock_foo.assert_called_once_with(1)
So in this case, you mock the entire Foo class.
Then, there is this syntax mock_foo.return_value.x = 2: where mock_foo.return_value simply means the return object when calling Foo(1) - which is your object. Since we mocked the entire class - the __init__ method does nothing - so you need to set the x attribute on your own.
Also note the mock_foo.assert_called_once_with(1) - which checks that Foo(1) was called with the right parameter.
p.s.
To simplify this kind of mocking, I created a pytest fixture called pytest-mock-generator. You can use it to help you create the mocks and asserts.
You start with using the mg fixture to analyze your bar method so it locates the relevant mocks for you:
def test_bar(mocker, mg):
mg.generate_uut_mocks(bar)
When this test method is executed, it generates the following code (prints it to the console and copies it to your clipboard for quick usage):
# mocked dependencies
mock_Foo = mocker.MagicMock(name='Foo')
mocker.patch('test.Foo', new=mock_Foo)
You then modify the test function and execute the bar method and use the generate_asserts capability:
def test_bar(mocker, mg):
# mocked dependencies
mock_Foo = mocker.MagicMock(name='Foo')
mocker.patch('test.Foo', new=mock_Foo)
bar()
mg.generate_asserts(mock_Foo)
This gives you the following output:
assert 1 == mock_Foo.call_count
mock_Foo.assert_called_once_with(1)
mock_Foo.return_value.x.__add__.assert_called_once_with(1)
You don't need most of it, but you can keep the second line for your assert and the modify the third line so x has the right value:
def test_bar(mocker):
mock_foo = mocker.MagicMock(name='Foo')
mocker.patch('test.Foo', new=mock_foo)
mock_foo.return_value.x = 2
assert bar() == 3
mock_foo.assert_called_once_with(1)