在Python单元测试中单独模拟多个API请求

时间:2019-04-02 18:30:42

标签: python unit-testing mocking python-requests flask-restful

我有Flask views.py单元测试,该单元测试调用了其他REST API。如何专门模拟其中一个请求?

原因是如果状态码为200,则请求之一将触发某些操作,例如提交数据库,覆盖文件等。我想检查状态码是否返回200。如果是,我想防止单元测试中的后续操作,如果没有,那么无论如何都不会执行任何后续操作,所以不用担心。

我还希望模拟的请求完全不影响Flask应用程序的请求,即Flask应用程序的请求没有被模拟。

project / views.py

from flask import Flask
from project.another_dir.another_script import another_function

app = Flask(__name__)

@app.route('/api/abcde', methods=['POST'])
def post_something():
    another_function()

project / another_dir / another_script.py

import requests

def another_function():
    response = requests.post(<some_url>)    # this is the "requests" I want to mock

    if response.status_code == 200:
        # server working properly, commit database transaction / write to a file / trigger some other functions / ...
    else:
        # something's wrong with the server, send error for exception handling

单元测试

from unittest.mock import Mock
import pytest

headers = {'Authorization': 'Basic akd39K045Pw=='}
data = "some_data"

@pytest.fixture
def client():
    app.testing = True
    client = app.test_client()

    return client

@pytest.mark.parametrize("h, d, status_code", [
    (None, None, 401),  # no auth header, no data
    (None, data, 401),    # no auth header
    (headers, data, 200)  # with auth header and data
])
def test_views_post_something(client, h, d, status_code):

    ##### This is what I want to mock to avoid actually committing to db
    # from project.another_dir.another_script import requests
    # mock_request = Mock()
    # requests = mock_request
    ##### But no luck

    response = client.post('/api/abcde', headers=h, data=d)

    assert response.status_code == status_code

1 个答案:

答案 0 :(得分:0)

您是否尝试过pookunmock?它们服务于不同的用例,但在这种情况下,听起来pook更合适。如果您要嘲笑的请求不会发生太大变化并且属于私有/内部API,则Pook会很好地工作

另一种选择是使用诸如docker-compose之类的工具来旋转所选数据库的临时堆栈。这样,您可以在不接触任何脆弱资源的情况下让请求执行,但是如果您试图重新创建复杂的状态,这通常会更慢并且容易出错。我通常从pookunmock之类的低接触性方法开始,然后为最关键的任务测试构建临时表。