kaste / mockito-python

Mockito is a spying framework
MIT License
123 stars 12 forks source link

Mocking sys.argv and sys.stdout like in patch #24

Open relte opened 5 years ago

relte commented 5 years ago

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'))
kaste commented 5 years ago

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.

kaste commented 5 years ago

Two cents here:

@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?)

relte commented 5 years ago

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.

kaste commented 5 years ago

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.)