python mock.mock_calls不遵循@timeout修饰函数内部的调用

时间:2017-11-24 21:44:55

标签: python unit-testing mocking

我正在使用mock对函数进行单元测试,并尝试测试是否对模拟对象进行了调用。在下面的代码中,requests.post对象被模拟,我跟踪requests.post.mock_calls列表。

在以下代码中

代码构造:

import timeout_decorator

def block_funds(trader_id, amounts):

    @timeout_decorator.timeout(3, use_signals=False)
    def _block_funds(block_url, amounts):

        # requests.post.mock_calls empty here
        result = requests.post(url=block_url, data=amounts)
        # requests.post.mock_calls here has correct call recorded

        return result.status_code

    block_url = 'http:/someurl/somepath/{trader_id}'.format(trader_id=trader_id)

    try:

        # requests.post.mock_calls empty here
        code = _block_funds(block_url, amounts)
        # requests.post.mock_calls empty again here

    except timeout_decorator.TimeoutError as ex:
        logger.error('request failed')
        code = 500

    return code

在调用code = _block_funds(block_url, amounts)之后,我希望模拟对象记录对它的所有调用,但是一旦执行退出内部超时包装函数{{1,mock_calls列表就会被清空}}。模拟对象肯定是一样的,我遵循模拟ID来确保对象没有改变。

我做错了什么以及如何让模拟不要忘记它的来电?

1 个答案:

答案 0 :(得分:0)

我发现了这个问题,它在超时装饰器中,特别是 - 在use_signals=False部分。根据{{​​3}},要在我的场景中正确使用超时(多线程Web应用程序),您需要不使用信号并依赖多处理,在这种情况下,我会看到导致问题的意外模拟。如果我删除use_signals=False或完全删除装饰器 - 它可以正常工作。

我现在的解决方案是嘲笑装饰器本身也避免了这个问题。

<强>校正

直接嘲笑装饰者结果是不切实际的。相反,我把它包裹起来并嘲笑包裹:

def timeout_post(**kwargs):
    @timeout_decorator.timeout(3, use_signals=False)
    def _post(**kwargs):
        return requests.post(**kwargs)

    return _post(**kwargs)