mockito-python
mockito-python copied to clipboard
Getting the mocked obj instance in the mock method
Hello ! First, I really like mockito-python :heart:
Now my problem :)
If I want to mock the method of a class with thenAnswer
and then have access to the instance self
inside the stub function. I've tried different ways but I don't find any way to do so:
from mockito import when
class A:
def __init__(self, a):
self.a = a
def method(self):
print(self.a)
def fake_method(self_A):
print("fake:", self_A.a)
when(A).method().thenAnswer(fake_method)
A(10).method()
# > TypeError: fake_method() missing 1 required positional argument: 'self_A'
With pytest.monkeypatch
or pytest-mock
, I usualy use functools.partialmethod
to do that, but mockito tries to call directly the partialmethod and fails.
I've looked inside and the culprit seems to be the throw-away of self/cls in new_mocked_method
so I think there is no way to get self in the mock.
Thank for the help. I'm open to do a PR but I failed to make it works easily....
That is by design. ~~Initially thenAnswer
was used internally and then exposed later~~*. Typically it makes writing answer-functions easier.
What's the use case here? Ideally answers from stubs/mocks are constants or sort of hard-coded.
* It is actually introduced by #1 and tries to mimic the java library
I try to make a method fail in some cases, and only once. The solution i tired to implement was to thenAnswer the original method after a first mock that fails.
I've seen the other ticket about thenCallRealMethod
that would be really usefull. Currently, I've implemented my partial failing mock with classic mocking.
That sounds like the other way around from your original posting because you want to call through to the original code. (In the OP you defined a function fake_method
on the module level.)
There seems to be a bug or limitation here in that
> spy2(A.method)
> A().method()
also throws for the very same reason.
It works when you patch the instance though. E.g.
> a = A()
> spy2(a.foo)
> a.foo()
Not sure what to make with this. Do you need to patch A
t.i. you don't have control over the instantiation? Example code would help probably.
Ok, I will mix up my answers to be specific :)
I need to mock a function but only once. For instance, if there was thenCallRealMethod
, I would do:
from mockito import when
class A:
def method(self):
print(self)
when(A).method().thenRaise(Exception).thenCallRealMethod()
with retry():
A().method()
That's not true unit-tests with mocks. It is for integration tests but in non-nominal cases to check the robustsness of the code. The expressiveness of mockito would be really usefull even in those cases :)
An implementation of thenCallOriginalImplementation
is welcome. Of course, the example, if you test a retry
-er you really want mocked/stubbed answers. A retry-er is generic.
For the code you gave, as I said, it at least works with instances.
a = A()
detached_method = a.method
when(a).method().thenRaise(ValueError).thenAnswer(detached_method).thenReturn("mocked")
This would be more convenient if we also had the reverse API. E.g.
doAnswer(a.method).when(a).method()
as we only need the detached_method
trick because a.method
gets patched before thenAnswer
is evaluated.
That being said, I'm interested in the thenCallOriginalImplementation
thing.
Ah, we can close this as you fixed it.