当使用`patch`作为上下文管理器时,我怎样才能模拟和添加一个目标?

问题描述 投票:1回答:1

我有一个非常简单的模块,像这样。

def do(url):
    try:
        check(url)
        foo(url)
    except:
        bar(url)

def check(url):
    # some other stuff
    if ' ' in url:
        raise Exception('oops')

单元测试 do 我需要嘲讽 check,否则会有一些副作用。

from unittest.mock import patch
from main import do

def test_check_process():
    with patch('main.check') as method:
        do('http://something')
        assert method.call_count == 1

我的问题是,我还需要(模拟的) check 函数有时会抛出一个异常。该 patch 函数能够通过该函数提供一个目标。new 关键字,但当我改成给目标函数打补丁时,我得到一个错误,如 AttributeError: 'function' object has no attribute 'call_count'.

def mock_checker(url):
    if ' ' in url:
        raise Exception('oops')

def test_check_process():
    with patch('main.check', new=mock_checker) as method:
        do('http://something')
        assert method.call_count == 1

看起来,当提供 new 参数,即 patch 上下文管理器不是一个常规的补丁对象,我根本无法窥视它。

我应该如何使用 unittest 模块?

python unit-testing mocking python-unittest
1个回答
0
投票

你定义了一个新的 mock_checker 函数,它不是mock对象。该 呼叫次数 属性只存在于 unittest.mock.Mock. 我们可以使用 副作用 为模拟对象引发一个异常。

例如

main.py:

def do(url):
    try:
        check(url)
        foo(url)
    except:
        bar(url)


def check(url):
    if ' ' in url:
        raise Exception('oops')


def foo(url):
    pass


def bar(url):
    pass

test_main.py:

from unittest.mock import MagicMock, patch
from main import do


def test_check_process():
    with patch('main.check', side_effect=Exception('oops')) as mock_check:
        print(mock_check)
        do('http://something')

        assert mock_check.call_count == 1


def test_check_process_2():
    mock_checker = MagicMock(side_effect=Exception('oops'))
    with patch('main.check', new=mock_checker) as mock_check:
        print(mock_check)
        do('http://something')
        assert mock_check.call_count == 1


if __name__ == '__main__':
    test_check_process()
    test_check_process_2()

执行结果。

<MagicMock name='check' id='4535123472'>
<MagicMock id='4535121168'>

断言成功

© www.soinside.com 2019 - 2024. All rights reserved.