Doubles and contextlib
I'm trying to use doubles with a class that uses the @contextmanager decorator on a method: https://docs.python.org/2/library/contextlib.html
However, this fails because __enter__ and __exit__ are not properly handled on the double. Any way to add this functionality to doubles? Or am I holding it wrong?
I would expect something like this to work:
from contextlib import contextmanager
from doubles import expect, ObjectDouble
class Stats(object):
@contextmanager
def timed(self, key):
pass
def test__timed_does_stuff():
d = ObjectDouble(Stats())
expect(d).timed.once()
with d.timed('mykey'):
pass
Currently the only way to do this would be to mock enter/exit manually on your object double.
e.g.
expect(d).__enter__
expect(d).__exit__
I need to think a little bit if doing this automagically is a feature we want to add.
@toddsifleet Thanks for your answer. My problem is complicated by the fact that there are multiple methods on the Stats class I want to test/mock and only one that has the @contextmanager decorator:
class Stats(object):
@contextmanager
def timed(self, key):
pass
def count(self, key):
pass
So if I mock the whole Stats class using e.g. ObjectDouble (so stats_mock = ObjectDouble(Stats())), I'm not actually sure how I mock the __enter__ and __exit__ separately on just one method?
@markuswustenberg I couldn't think of a good way to do this...but I something like this would work:
from contextlib import contextmanager
from doubles import expect, ObjectDouble
class Stats(object):
@contextmanager
def timed(self, key):
pass
def count(self, key):
print 'count called'
class MyTimed(object):
def __init__(self, key):
self.key = key
def __enter__(self, *args, **kwargs):
print self.key
return self
def __exit__(self, *args, **kwargs):
print self.key
my_double = ObjectDouble(Stats)
expect(my_double).timed.and_return_result_of(lambda x: MyTimed(x))
with my_double.timed('foobar') as foo:
print foo
Output:
$ python test.py
foobar
<__main__.MyTimed object at 0x109d0cbd0>
foobar
I will try to think how we can generalize this and add it to doubles.
Cool, thanks a lot!