Search code examples
pythonflaskpytest

Mocking db connections and return values inside a flask route


I have the following flask app route:

# routes.py

from flask import jsonify
from app.utils.db import db_connection, db_query

@api.route("/some/route", methods=["GET"])
@auth
def get_data_for_some_route(**kwargs) -> List[Dict]:

    # connect to db
    db_client = db_connection()
 
    # Query db for data
    data = db.query(db_client, GET_STUFF)

    # parse the data example
    parsed_data = data[0]
    
    return jsonify(parsed_data), 200

How can I write a pytest for this route, but mock the db connection and query results?

# test_routes.py

import pytest
from fixtures import SOME_ROUTE_JSON_DATA

mock_token = "12345"

def test_get_data_for_some_route(mocker, client):
    querystring1 = 'Hello'
    querystring2 = 'World'

    # Mock db query function
    mocked_db_query = mocker.patch('app.utils.database.db_connection')
    mocked_db_query.return_value = loads(SOME_ROUTE_JSON_DATA)

    # Call the route
    response = client.get(
        f"/some_route",
        headers={"Authorization": f"{mock_token}"}
    )

    # assert response.json is some value I expect it to be

I'm a little confused how to mock values within the route. So the database connection can be ignored and I can also say 'this is what the return data will be in this case, continue on testing the function pretending that is what the data is.'


Solution

  • To patch a function you need to provide the full path to the function being patched. In your case both db_connection and db_query need to be patched. You could do something like this:

    import pytest
    from app import app
    
    # Sample JSON data for testing
    SOME_ROUTE_JSON_DATA = '{"key": "value"}'
    
    # Mock token for authorization
    mock_token = "12345"
    
    @pytest.fixture
    def client():
        """Create a test client using Flask app context."""
        with app.test_client() as client:
            yield client
    
    def test_get_data_for_some_route(mocker, client):
        # Mock db_connection and db_query functions
        mocked_db_connection = mocker.patch("app.utils.database.db_connection")
        mocked_db_query = mocker.patch("app.utils.database.db_query")
        
        # Set the return value for db_query to the sample JSON data
        mocked_db_query.return_value = json.loads(SOME_ROUTE_JSON_DATA)
    
        # Call the route with mocked data
        response = client.get(
            "/some_route",
            headers={"Authorization": f"Bearer {mock_token}"}
        )
    
        # Assert response status code
        assert response.status_code == 200
    
        # Assert response JSON data
        expected_data = {"key": "value"}  # Define the expected JSON response
        assert response.get_json() == expected_data
    
        # Assert that db_connection and db_query were called with expected arguments
        mocked_db_connection.assert_called_once()
        mocked_db_query.assert_called_once_with(mocked_db_connection.return_value, "GET_STUFF")