简体   繁体   中英

mocking a standard library calls in py.test

I'm learning how to write tests with py.test, but I can't get idea how to mock external calls.

Let say I have a code for testing:

app.py:

import random

def trade_robot(stock, price):
    return ' '.join((random.choice(('buy', 'sell', 'keep')), stock))

And I want to be sure I check case for random.choice deciding I need to buy (and I want to check it properly join strings for 'buy' case).

my test code should look like this:

import pytest
from app import trade_robot
import sys

def test_buy_case():
    # some mock magic here
    assert trade_robot('AAPL', 500) == 'buy AAPL'

if __name__ == "__main__":
    pytest.main("-v %s" % sys.argv[0])

What should be in 'some mock magic' to make this test passing every time? Thanks!

That can be done with the library mock , which is included into standard library since Python 3.3.

First, with a context manager:

import random
with mock.patch.object(random, 'choice') as m:
    m.return_value = 'buy'
    print random.choice(['anything'])  # prints 'buy' regardless of the arguments

The same with a decorator:

@mock.patch.object(random, 'choice')
def test_buy(m):
    m.return_value = 'buy'
    print random.choice(['anything'])

The library also allows making assertions regarding mock calls and irreplaceable for unit testing. Alternatively, some people prefer explicit dependency inversion, which means passing the function random.choice into your code as a function/method/constructor argument and replacing it with a mock in a test.

You could use the 'patch' decorator to mock external calls:

http://www.voidspace.org.uk/python/mock/patch.html

Eg you could mock the 'random.choice' with

@patch('random.choice')
def test_foo(choice):
    choice.return_value = some value 

The key is where to patch: http://www.voidspace.org.uk/python/mock/patch.html#id1

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM