4

One of the mocks that I'm using contains the call call().__str__().

Output of my_mock.mock_calls

[call(<MagicMock name='mock()' id='140630678530704'>, indent=2, sort_keys=True),
 call().__str__(),            # <-- what I'm trying to represent
 call()]

How can I represent this?

Checking that call().__str__() is part of the mock_calls is causing me difficulty as that will get converted to the string 'call()'.

In [16]: mock.call().__str__()
Out[16]: 'call()'
aydow
  • 3,673
  • 2
  • 23
  • 40

2 Answers2

2

You could solve using a tuple like this:

inst.assert_has_calls([
    ("().__str__", (), {})
])

It works because call is unittest.mock._Call class alias, and _Call is a subclass of tuple.

So when you write ("().__str__", (), {}) the items are:

  1. name is "().__str__"
  2. args are ()
  3. kwargs are {}

Which equals call().__str__(). To show you some examples in the interpreter:

>>> from unittest.mock import _Call
>>> print(_Call(("().__str__", (), {})))
call().__str__()
>>> print(_Call(('name', (1,), {})))
call.name(1)
>>> _Call(('Class().__str__', (), {}))
call.Class().__str__()
Intrastellar Explorer
  • 3,005
  • 9
  • 52
  • 119
0

If I understand you correctly, you want to check if the given call is in mock_calls. The standard way to check if a method has been called, is to use one of the assert_called_xxx methods on the created instance:

@mock.patch('mymodule.SomeClass')
def test1(mocked):
    inst = SomeClass()  # inst == mocked.return_value
    inst.__str__.assert_not_called()

    # use this if you don't have inst
    mocked.return_value.__str__assert_not_called()

    print(inst)
    inst.__str__.assert_called_once()
    mocked.return_value.assert_called_once()
    mocked.return_value.__str__.assert_called_once()

Note that instead of checking call().__str__ on mocked, you check __str__ on mocked.return_value, which is the result of call().

If for some reason you need to directly check for the string representation of that call, e.g. call.__str__(), you have to check the string instead:

assert 'call.__str__()' in [str(c) for c in inst.mock_calls]

Or, if you want to check it on the class:

assert 'call().__str__()' in [str(c) for c in mocked.mock_calls]

EDIT: Removed not working version, as pointed out by @user2357112supportsMonica, fixed incorrect usage of mocked.

MrBean Bremen
  • 14,916
  • 3
  • 26
  • 46
  • `mocked.__str__` is not a mock and does not have an `assert_called_once` method. You'll get an `AttributeError` if you try that. – user2357112 May 26 '20 at 06:37
  • The `mocked.__str__ in mocked.mock_calls` check produces a variety of hangs and incorrect results when I test it, too. – user2357112 May 26 '20 at 06:40
  • Ok, that's strange, I tested it ok - did you use `mock.patch` to patch `SomeClass`? Can you check the type of `mocked` and `mocked.__str__`? Both should be `MagicMock`. – MrBean Bremen May 26 '20 at 06:42
  • Looks like it is a MagicMock if you use a MagicMock. However, the hangs and wrong results for the `in` check still happen with a MagicMock. For example, [the `in` check I'm linking now hangs](https://ideone.com/7ihHsT). – user2357112 May 26 '20 at 06:45
  • Ok, I think I understand the difference - you directly create a `MagicMock`, while I create the mock from a real class, that always have a `__str__` method. I can reproduce your problem, but that is because the `MagicMock` is not initialized with an object. – MrBean Bremen May 26 '20 at 06:49
  • [The hangs still happen with `patch`.](https://ideone.com/PvpFVg) – user2357112 May 26 '20 at 06:52
  • Well, you don't use the mock - you have to check that on the mock (e.g. `mock.mock_calls` instead of `x.mock_calls`. – MrBean Bremen May 26 '20 at 07:00
  • Right you are, that part is indeed wrong - I removed it from the answer - thank you! I was obviously confused... – MrBean Bremen May 26 '20 at 08:32