在py.test中模拟标准库调用

时间:2016-01-12 14:09:21

标签: python tdd pytest

我正在学习如何使用py.test编写测试,但我无法了解如何模拟外部调用。

假设我有一个测试代码:

app.py:

import random

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

我想确保我检查一下case.choice决定我需要购买(我想检查它是否正确加入字符串以及#39;购买'案例)。

我的测试代码应如下所示:

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

应该包含什么样的模拟魔法'每次都要通过这个测试?谢谢!

2 个答案:

答案 0 :(得分:3)

可以使用库mock完成,自Python 3.3以来,它已包含在standard library中。

首先,使用上下文管理器:

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

与装饰者相同:

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

该库还允许对模拟调用进行断言,并且对于单元测试不可替代。或者,有些人更喜欢显式依赖项反转,这意味着将函数random.choice作为函数/方法/构造函数参数传递给代码,并在测试中将其替换为模拟。

答案 1 :(得分:1)

您可以使用'补丁'装饰器模拟外部调用:

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

E.g。你可以嘲笑随机选择'与

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

关键是修补的地方: http://www.voidspace.org.uk/python/mock/patch.html#id1