Skip to content

Commit

Permalink
allow passing mock name to mocker.stub()
Browse files Browse the repository at this point in the history
This allows customizing the stub's name displayed in any assertion failure
messages (useful for debugging), without having to resort to setting `Mock`
object's internal `_mock_name` attribute directly.
  • Loading branch information
jurko-gospodnetic committed May 15, 2016
1 parent 485302d commit 43d5246
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 11 deletions.
3 changes: 2 additions & 1 deletion README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -119,14 +119,15 @@ Stub
*New in version 0.6*

The stub is a mock object that accepts any arguments and is useful to test callbacks, for instance.
May be passed a name to be used by the constructed stub object in its repr (useful for debugging).

.. code-block:: python
def test_stub(mocker):
def foo(on_something):
on_something('foo', 'bar')
stub = mocker.stub()
stub = mocker.stub(name='on_something_stub')
foo(stub)
stub.assert_called_once_with('foo', 'bar')
Expand Down
5 changes: 3 additions & 2 deletions pytest_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,16 @@ def spy(self, obj, name):
autospec=autospec)
return result

def stub(self):
def stub(self, name=None):
"""
Creates a stub method. It accepts any arguments. Ideal to register to
callbacks in tests.
:param name: the constructed stub's name as used in repr
:rtype: mock.MagicMock
:return: Stub object.
"""
return mock_module.MagicMock(spec=lambda *args, **kwargs: None)
return mock_module.MagicMock(spec=lambda *args, **kwargs: None, name=name)

class _Patcher(object):
"""
Expand Down
37 changes: 29 additions & 8 deletions test_pytest_mock.py
Original file line number Diff line number Diff line change
Expand Up @@ -168,14 +168,35 @@ def test_mocker_resetall(mocker):
assert not open.called


def test_mocker_stub(mocker):
def foo(on_something):
on_something('foo', 'bar')

stub = mocker.stub()

foo(stub)
stub.assert_called_once_with('foo', 'bar')
class TestMockerStub:
def test_call(self, mocker):
stub = mocker.stub()
stub('foo', 'bar')
stub.assert_called_once_with('foo', 'bar')

def test_repr_with_no_name(self, mocker):
stub = mocker.stub()
assert not 'name' in repr(stub)

def test_repr_with_name(self, mocker):
test_name = 'funny walk'
stub = mocker.stub(name=test_name)
assert "name={!r}".format(test_name) in repr(stub)

def __test_failure_message(self, mocker, **kwargs):
expected_name = kwargs.get('name') or 'mock'
expected_message = 'Expected call: {}()\nNot called'.format(expected_name)
stub = mocker.stub(**kwargs)
with pytest.raises(AssertionError) as exc_info:
stub.assert_called_with()
assert exc_info.value.msg == expected_message

def test_failure_message_with_no_name(self, mocker):
self.__test_failure_message(mocker)

@pytest.mark.parametrize('name', (None, '', 'f', 'The Castle of aaarrrrggh'))
def test_failure_message_with_name(self, mocker, name):
self.__test_failure_message(mocker, name=name)


def test_instance_method_spy(mocker):
Expand Down

0 comments on commit 43d5246

Please sign in to comment.