[파이썬] requests 요청 테스트 및 모킹

In Python, the requests library is widely used for sending HTTP requests and handling responses. It provides a simple and intuitive interface for making HTTP calls and is often used in web scraping, API consumption, and testing.

This blog post will focus on testing and mocking requests in Python, specifically using the requests-mock library. requests-mock allows you to effectively test code that interacts with external APIs by simulating HTTP requests and responses.

Installation

To get started, you need to install the requests and requests-mock libraries in your Python environment. You can use the following pip command to install both libraries:

pip install requests requests-mock

Basic Usage

Here’s a basic example of how to use requests-mock to mock requests in your tests:

import requests
import requests_mock

with requests_mock.Mocker() as mocker:
    mocker.register_uri(
        'GET',
        'https://api.example.com/users',
        json={'users': [{'name': 'John'}, {'name': 'Jane'}]}
    )

    response = requests.get('https://api.example.com/users')
    data = response.json()

    assert response.status_code == 200
    assert data['users'][0]['name'] == 'John'

In the above example, we use requests-mock to mock a GET request to the specified URL (https://api.example.com/users). We define the response body as a JSON object with a list of users. We then make a request using requests as usual and verify that the response status code is 200 and the first user’s name is “John”.

Advanced Usage

requests-mock provides more advanced features to mock different types of requests and responses, handle multiple endpoints, and dynamically generate responses. Here are a few examples:

Mocking Different Types of Requests

import requests
import requests_mock

with requests_mock.Mocker() as mocker:
    mocker.get('https://api.example.com/get', json={'response': 'GET'})
    mocker.post('https://api.example.com/post', json={'response': 'POST'})
    mocker.put('https://api.example.com/put', json={'response': 'PUT'})
    mocker.delete('https://api.example.com/delete', json={'response': 'DELETE'})

    get_response = requests.get('https://api.example.com/get')
    post_response = requests.post('https://api.example.com/post')
    put_response = requests.put('https://api.example.com/put')
    delete_response = requests.delete('https://api.example.com/delete')

    assert get_response.json()['response'] == 'GET'
    assert post_response.json()['response'] == 'POST'
    assert put_response.json()['response'] == 'PUT'
    assert delete_response.json()['response'] == 'DELETE'

In this example, we mock different types of requests (GET, POST, PUT, DELETE) to different endpoints and verify that the responses match the expected values.

Handling Multiple Endpoints

import requests
import requests_mock

with requests_mock.Mocker() as mocker:
    mocker.get('https://api.example.com/users', json={'users': [{'name': 'John'}]})
    mocker.get('https://api.example.com/products', json={'products': [{'name': 'Keyboard'}]})

    users_response = requests.get('https://api.example.com/users')
    products_response = requests.get('https://api.example.com/products')

    assert users_response.json()['users'][0]['name'] == 'John'
    assert products_response.json()['products'][0]['name'] == 'Keyboard'

In this example, we mock requests to different endpoints (/users and /products) and verify that the responses contain the expected data.

Dynamic Responses

import requests
import requests_mock

def dynamic_response(request, context):
    if 'users' in request.url:
        context.status_code = 200
        context.json = {'users': [{'name': 'John'}]}
    elif 'products' in request.url:
        context.status_code = 200
        context.json = {'products': [{'name': 'Keyboard'}]}
    else:
        context.status_code = 404

with requests_mock.Mocker() as mocker:
    mocker.get('https://api.example.com', json=dynamic_response)

    users_response = requests.get('https://api.example.com/users')
    products_response = requests.get('https://api.example.com/products')
    unknown_response = requests.get('https://api.example.com/unknown')

    assert users_response.json()['users'][0]['name'] == 'John'
    assert products_response.json()['products'][0]['name'] == 'Keyboard'
    assert unknown_response.status_code == 404

In this example, we define a dynamic response function (dynamic_response) that examines the request URL and generates appropriate responses based on the URL path. We then register this function as the response for any request to https://api.example.com. We verify that the responses contain the expected data or return a 404 status code if the URL is unknown.

Conclusion

Testing and mocking requests in Python is crucial when developing applications that rely on external APIs. The requests-mock library simplifies the process of mocking requests and responses, allowing you to effectively test your code. With the techniques discussed in this blog post, you can confidently test your code’s behavior in a controlled environment without the need for real network requests. Happy testing!