Closed stacymiller closed 2 years ago
Ah that works different. You actually did not mock B
but assigned a dummy object ("mock") to B
. After that the class B(A):
gets garbage collected if it's not referenced anywhere else.
You can mock/stub/patch or better: configure the behavior of B without changing the implementation of B. E.g.
In [68]: class A:
...: @staticmethod
...: def foo():
...: return "result"
...:
...: class B(A):
...: pass
...:
In [69]: when(B).foo().thenReturn(12)
Out[69]: <mockito.invocation.AnswerSelector at 0x1a6bf2c2da0>
In [70]: B().foo()
Out[70]: 12
In [71]: B.foo()
Out[71]: 12
In [72]: unstub()
In [73]: B().foo()
Out[73]: 'result'
The documentation you link to says "Unstubs all stubbed methods and functions". (Not: remove all mocks). That usually means restore all original functionality, or: "unpatch".
FWIW unstub
does nothing here:
In [75]: C = mock()
In [76]: C.foo()
In [77]: when(C).foo().thenReturn(42)
Out[77]: <mockito.invocation.AnswerSelector at 0x1a6bf16ec80>
In [78]: C.foo()
Out[78]: 42
In [79]: unstub()
In [80]: C.foo()
Out[80]: 42
I don't know if there is a use-case here. Usually mock
s are short lived and you just create a new one.
Thank you! Now I can see this is an intended behaviour and understand why is it so.
Usually mocks are short lived and you just create a new one.
Usually yes, but not when you're doing Model.query = mock()
in the sqlalchemy and this affects the whole test suite >_<
Ok, now I got what's happening here and will try to find a solution. Thank you!
Oh, Model.query = mock()
, is that flasks sqlalchemy layer? That is extremely ugly to mock as just accessing Model.query
already has a side-effect. (Yeah, sure, it's a getter, LOL.)
I will make a patch so that mock
objects are also reset on unstub
. (Although I don't think this will help you here.)
The shitty, ahem tricky, thing is that query
is a class descriptor, and of course the fluent interface of sqlalchemy is wordy to mock. That's a usecase for #3 actually.
I think the following works:
query_prop = mock()
when(query_prop).filter_by(...).thenReturn(
mock({"first": lambda: "A user"})
)
with when(_QueryProperty).__get__(...).thenReturn(query_prop):
assert User.query.filter_by(username='admin').first() == "A user"
# or on pytest:
monkeypatch.setattr(User, "query", query_prop) # we don't mock the *private* `_QueryProperty`(!)
assert User.query.filter_by(username='admin').first() == "A user"
Two things for mockito, 1. make patching properties/descriptors easier, 2. support fluent interfaces ("chains").
Ideally:
with when(User).query.filter_by(...).first().thenReturn("A user"):
assert User.query.filter_by(username='admin').first() == "A user"
That would be extremely beautiful.
Hello! The following looks like a bug to me, but if it is not — please advice how to circumvent this behaviour.
Steps to reproduce: run the following code
Expected behaviour:
"result"
is printed. Actual behaviour in mockito-1.3.3 installed from PyPI on Python 3.9:"None"
is printed.I expect that when I first mocked B and then unstubbed all mocks,
B.foo()
should execute the inherited methodA.foo()
and return me the string"result"
. What happens is that B.foo() returns the Dummy object. Which seems strange, because the documentation forunstub()
promises to remove all mocksI believe I saw a similar bug report somewhere in 2016, but I did not manage to find it again and attach it here.
Thanks in advance for any advice!