mockito-python
mockito-python copied to clipboard
Mocking sys.argv and sys.stdout like in patch
Is it possible to use Mockito to replace sys.argv
or sys.stdout
?
I could do it with unittest.mock.patch
but I'd rather use a single mocking tool:
def it_outputs_answers_based_on_an_argument(when):
with patch('sys.argv', ['cli.py', 'all']):
when('app.cli.ApiClient').search_answers('all').thenReturn([
{
'id': 1,
'question': 'A?',
'content': 'B'
}
])
with patch('sys.stdout', StringIO()) as stdout:
main()
output = stdout.getvalue().strip()
expect(output).to(equal('A?\n--\nB'))
Afaik this is not possible. Historically mockito is completely focused on stubbing/patching callables. I want this too and actually have it on my to-do list but you can try a PR if you want to.
Two cents here:
-
Since mocking and esp. monkey patching in python in general is very easy, if I look at your example code, it seems that testing and testability is not any guard and guide when designing the API anymore. E.g. if you had defined
def main(argv=sys.argv, stdout=sys.stdout)
(t.i with boring, standard dependency injection) there wouldn't be any need for monkey-patching. -
What you want patch to do is super simple.
@contextmanager
def patch(obj, attr, replacement):
original = getattr(obj, attr, None)
setattr(obj, attr, replacement)
try:
yield replacement
finally:
if original:
setattr(obj, attr, original)
else:
delattr(obj, attr)
It becomes more complicated within the mockito framework of course. (Do you know pytests's monkeypatch
fixture?)
True, with dependency injection it'd be another story but AFAIK it's not the "pythonic way" of doing things. I'm new to Python, especially the testing part and I find Mockito the friendliest for mocking.
I read about monkeypatch
but it doesn't seem much different from mocker.patch
. Or am I missing something?
By the way as to my test, I use Click now so it got simpler because of its helper.
I read about monkeypatch but it doesn't seem much different from mocker.patch. Or am I missing something?
monkeypatch
is far less complex. It's just a couple of lines, similar to what I posted above. mock.patch
is, just like mockito, way more code.
(I hate if people say something is not 'pythonic'. If it's a small tool, go and monkeypatch globals, if it grows inject the dependencies to stay flexible, extensible.)