There are several unit test frameworks available in Python. Try/except blocks are good for error handling, but you still need a separate unit test around the call if you want to unit test it.

You do have something you can test, you can just return it and test that in your unit test.

Example Unit test using unittest:

import unittest
import requests

class RestCalls():

    def google_do_something(blahblah):
        url= blahblah
        try:
            r = requests.get(url,timeout=1)
            r.raise_for_status()
            return r.status_code
        except requests.exceptions.Timeout as errt:
            print (errt)
            raise
        except requests.exceptions.HTTPError as errh:
            print (errh)
            raise
        except requests.exceptions.ConnectionError as errc:
            print (errc)
            raise
        except requests.exceptions.RequestException as err:
            print (err)
            raise


class TestRESTMethods(unittest.TestCase):

    def test_valid_url(self):
        self.assertEqual(200,RestCalls.google_do_something('http://www.google.com/search'))

    def test_exception(self):
        self.assertRaises(requests.exceptions.Timeout,RestCalls.google_do_something,'http://localhost:28989')

if __name__ == '__main__':
    unittest.main()

Executing should show (made some edits to this post, updated output included at bottom of post):

> python .\Tests.py
 .
----------------------------------------------------------------------
Ran 1 test in 0.192s

OK

If you asserted a different response code from your request, it would fail (the request is just returning http response codes):

python .\Tests.py
F
======================================================================
FAIL: test_upper (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".\Tests.py", line 25, in test_upper
    self.assertEqual(404,RestCalls.google_do_something('search'))
AssertionError: 404 != 200

----------------------------------------------------------------------
Ran 1 test in 0.245s

FAILED (failures=1)

Which is expected.

Edit: Included exception testing. You can test these by just including raise in the except block, which will show this after running:

> python .\Tests.py
HTTPConnectionPool(host='localhost', port=28989): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x03688598>, 'Connection to localhost timed out. (connect timeout=1)'))
..
----------------------------------------------------------------------
Ran 2 tests in 2.216s

OK

References:

  • Unit tests in Python
  • https://docs.python.org/3/library/unittest.html
  • https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
Answer from user176692 on Stack Overflow
🌐
Opensource.com
opensource.com › article › 21 › 9 › unit-test-python
3 ways to test your API with Python | Opensource.com
September 22, 2021 - In other words, you'll see the art of API unit testing in Python. Unit tests are meant to test a single unit of behavior. In testing, a well-known rule of thumb is to isolate code that reaches external dependencies.
Top answer
1 of 3
5

There are several unit test frameworks available in Python. Try/except blocks are good for error handling, but you still need a separate unit test around the call if you want to unit test it.

You do have something you can test, you can just return it and test that in your unit test.

Example Unit test using unittest:

import unittest
import requests

class RestCalls():

    def google_do_something(blahblah):
        url= blahblah
        try:
            r = requests.get(url,timeout=1)
            r.raise_for_status()
            return r.status_code
        except requests.exceptions.Timeout as errt:
            print (errt)
            raise
        except requests.exceptions.HTTPError as errh:
            print (errh)
            raise
        except requests.exceptions.ConnectionError as errc:
            print (errc)
            raise
        except requests.exceptions.RequestException as err:
            print (err)
            raise


class TestRESTMethods(unittest.TestCase):

    def test_valid_url(self):
        self.assertEqual(200,RestCalls.google_do_something('http://www.google.com/search'))

    def test_exception(self):
        self.assertRaises(requests.exceptions.Timeout,RestCalls.google_do_something,'http://localhost:28989')

if __name__ == '__main__':
    unittest.main()

Executing should show (made some edits to this post, updated output included at bottom of post):

> python .\Tests.py
 .
----------------------------------------------------------------------
Ran 1 test in 0.192s

OK

If you asserted a different response code from your request, it would fail (the request is just returning http response codes):

python .\Tests.py
F
======================================================================
FAIL: test_upper (__main__.TestStringMethods)
----------------------------------------------------------------------
Traceback (most recent call last):
  File ".\Tests.py", line 25, in test_upper
    self.assertEqual(404,RestCalls.google_do_something('search'))
AssertionError: 404 != 200

----------------------------------------------------------------------
Ran 1 test in 0.245s

FAILED (failures=1)

Which is expected.

Edit: Included exception testing. You can test these by just including raise in the except block, which will show this after running:

> python .\Tests.py
HTTPConnectionPool(host='localhost', port=28989): Max retries exceeded with url: / (Caused by ConnectTimeoutError(<urllib3.connection.HTTPConnection object at 0x03688598>, 'Connection to localhost timed out. (connect timeout=1)'))
..
----------------------------------------------------------------------
Ran 2 tests in 2.216s

OK

References:

  • Unit tests in Python
  • https://docs.python.org/3/library/unittest.html
  • https://en.wikipedia.org/wiki/List_of_HTTP_status_codes
2 of 3
2

I am not sure that your approach is such a good idea (just printing something in case of an error) but you could mock the print function to see if it was really called (and with what arguments):

https://docs.python.org/3/library/unittest.mock.html?highlight=mock#module-unittest.mock

Edit:

Working with mocks is a bit tricky as far as I remember. You would have to mock the print function in the current module. Perhaps something like this (not tested ...):

from unittest.mock import patch
from unittest import TestCase

class TestGoogleDoSomething(TestCase)
    
    @patch("nameOfYourModule.print")
    def test_google_do_something(self, print_mock): # the decorator will pass the mock object into the function
        g = google_do_something('blahblah')
        print_mock.assert_called_with("your error message here ...")
Discussions

python - How to write a unit test code for functions which make API requests to web? - Stack Overflow
And, since you are using requests module in the actual code, it is better you MOCK the API calls while writing the unit-tests. It doesn't make an API call from the test function because we use a python mock. More on stackoverflow.com
🌐 stackoverflow.com
unit testing - How do I test an API Client with Python? - Stack Overflow
I'm working on a client library for a popular API. Currently, all of my unit tests of said client are making actual API calls against a test account. Here's an example: def test_get_foo_settings(... More on stackoverflow.com
🌐 stackoverflow.com
How to unit test a service which makes multiple external api calls
You're doing something wrong. You can definitely mock multiple entities. One common gotcha is mocking in the wrong place. It should happen where whatever you're mocking is used, not where it's defined. More on reddit.com
🌐 r/learnpython
6
2
February 19, 2024
How to test an API request to the external system
Postman is also great for API testing. More on reddit.com
🌐 r/Python
5
32
May 5, 2023
🌐
Miguendes
miguendes.me › 3-ways-to-test-api-client-applications-in-python
3 Ways to Unit Test REST APIs in Python
September 19, 2020 - Master REST API testing in Python. Learn how to test HTTP calls to an external API using VCR.py, pytest-mock and the responses / requests libraries.
🌐
Medium
medium.com › hackernoon › writing-unit-tests-for-rest-api-in-python-web-application-2e675a601a53
Writing Unit Tests for REST API in Python | by Parth Shandilya | HackerNoon.com | Medium
January 12, 2020 - To test this function, I basically created a mock object which could simulate the behavior of real objects in a controlled way, so in this case a mock object may simulate the behavior of the output function and return something like an JSON response without hitting the real REST API. Now the next challenge is to parse the JSON response and feed the specific value of the response JSON to the Python automation script. So Python reads the JSON as a dictionary object and it really simplifies the way JSON needs to be parsed and used. And here’s the content of the backend/tests/test_basic.py file.
🌐
Real Python
realpython.com › testing-third-party-apis-with-mocks
Understanding the Python Mock Object Library – Real Python
January 18, 2025 - To write a mock test in Python, you use the unittest.mock library to create mock objects and substitute them for real objects in your code, allowing you to test how your code interacts with those objects. How can you assert that a mock method was called with specific arguments?Show/Hide
Find elsewhere
🌐
Blazemeter
blazemeter.com › blog › python-api-testing
How to Do Python API Testing with Apiritif | Perforce BlazeMeter
The approach toward unit testing is the same in most programming languages and frameworks, including Python API testing. Every test case is a function or method, and there can be multiple test cases per file and multiple files of tests. Each of the test cases' implementation code calls the operation it wants to test (plus the necessary boilerplate and setup code) and contains one or more assertions regarding the result.
🌐
On Test Automation
ontestautomation.com › writing-tests-for-restful-apis-in-python-using-requests-part-1-basic-tests
Writing tests for RESTful APIs in Python using requests – part 1: basic tests | On Test Automation
December 12, 2019 - I prefer pytest, but requests works equally well with other Python unit testing frameworks. ... Then, all we need to do to get started is to create a new Python file and import the requests library using ... Our API under test For the examples in this blog post, I’ll be using the Zippopotam.us REST API.
🌐
Pytest With Eric
pytest-with-eric.com › pytest-best-practices › python-rest-api-unit-testing
Python REST API Unit Testing for External APIs | Pytest With Eric
November 18, 2022 - Mocking or Patching is the practice of telling the Unit Testing framework to return a specific value for a variable, function or class object instantiation. Let’s look at how this is achieved with some code. ... In this example, we’ll use the pytest-mock library, which is a wrapper around the patching API provided by the mock package. If you follow the source code, you’ll see that the list_breeds() , search_breeds() and create_vote() API methods use the call_api() class method.
🌐
CoderPad
coderpad.io › blog › development › how-to-test-python-rest-apis
How to Test Python REST APIs - CoderPad
June 5, 2023 - import unittest from unittest import TestCase from flask_api_5 import CustomFlaskAPI, PostOutput from flask import Flask, jsonify, request, views from marshmallow import Schema, fields, validate app = Flask(__name__) class PostOutput(Schema): answers = fields.Int( required=True, strict=True, # Must be a whole number validate=validate.Range(min=1), # Must be positive ) class CustomFlaskAPI(views.MethodView): def post(self): result = { "answers": request.json.get("children", 0) + 1, } errors = PostOutput().validate(result) if len(errors) != 0: # Errors instead of returning malformed data return
🌐
CodiLime
codilime.com › blog › software development › backend › testing apis with pytest: how to effectively use mocks in python
Testing APIs with PyTest: How to Effectively Use Mocks in Python
October 22, 2024 - You can mock the log_result method to focus your test on get_data. This might be especially useful when a mocked method has some indirect (hard to track) or unwanted side effects - it is slow, depends on external services, etc. Mocking lets you avoid all those difficulties, and only assert that the method was called as expected: ... import pytest from unittest.mock import patch from api_client import APIClient @pytest.fixture def mock_response(): with patch('requests.get') as mock_get: yield mock_get @patch.object(APIClient, 'log_result') def test_get_data_with_logging(mock_log_result, mock_response): mock_response.return_value.json.return_value = {'key': 'value'} client = APIClient() url = 'http://example.com/api' result = client.get_data(url) assert result.json() == {'key': 'value'} mock_log_result.assert_called_once()
🌐
My Developer Planet
mydeveloperplanet.com › 2020 › 03 › 11 › how-to-mock-a-rest-api-in-python
How to Mock a Rest API in Python - mydeveloperplanet.com
June 7, 2020 - We want to unit test the ... a call to the Jira Rest API. We do not want our unit test to be dependent of a third party service and therefore we need a way to mock the Rest API. There are several options to mock a Rest API, but we will make use of the requests-mock Python library which ...
🌐
Auth0
auth0.com › blog › mocking-api-calls-in-python
Mocking API calls in Python | Auth0
December 6, 2017 - The nose2 library extends the built-in Python unittest module to make testing easier. You can use unittest or other third-party libraries such as pytest to achieve the same results. The requests library simplifies HTTP calls in Python. For this tutorial, we will be communicating with a fake API on ...
🌐
DZone
dzone.com › data engineering › databases › how to mock a rest api in python
How to Mock a Rest API in Python
April 16, 2020 - Choose New - Python File and Python unit test. This creates the following default file: ... Running this unit test obviously fails (True does not equal False), but we do have set up the basics for writing our own unit tests now. We want to unit test the get_updated_issues function and this provides us a first challenge: the get_updated_issues function contains a call to the Jira Rest API...
🌐
Cosmicpython
cosmicpython.com › blog › 2020-01-25-testing_external_api_calls.html
Writing tests for external API calls
January 25, 2020 - Consider abstracting out a wrapper around your API · Use integration tests to test your adapter, and unit tests for your business logic (and to check that you call your adapter correctly)
🌐
Medium
medium.com › @khiljidanial › unit-test-for-gpt-external-api-call-in-python-a-practical-guide-c3a57893a28c
Unit test for GPT API in Python: A practical guide | by Danial Khilji | Medium
August 21, 2024 - The call_chatgpt function takes a prompt as input and returns the generated text from the GPT model. But since it relies on an external API, we need to carefully test it. ... We can use Python’s unittest.mock library to replace the actual API call with a mock object that simulates the behavior of the API.
🌐
Newtum
apitest.newtum.com › examples › python-unit-test-api-with-unittest
How to Unit Test an API in Python with `unittest` and `mock` | API Navigator
import unittest from unittest.mock import Mock, patch import requests # A simple function that interacts with an API def get_user_data(user_id): response = requests.get(f"https://api.example.com/users/{user_id}") response.raise_for_status() return response.json() class TestApi(unittest.TestCase): @patch('requests.get') def test_get_user_data_success(self, mock_get): # Configure the mock to return a successful response mock_response = Mock() mock_response.status_code = 200 mock_response.json.return_value = {'id': 1, 'name': 'John Doe'} mock_get.return_value = mock_response # Call the function u
🌐
Python
docs.python.org › 3 › library › unittest.mock.html
unittest.mock — mock object library
Mock allows you to assign functions (or other Mock instances) to magic methods and they will be called appropriately. The MagicMock class is just a Mock variant that has all of the magic methods pre-created for you (well, all the useful ones anyway). The following is an example of using magic methods with the ordinary Mock class: >>> mock = Mock() >>> mock.__str__ = Mock(return_value='wheeeeee') >>> str(mock) 'wheeeeee' For ensuring that the mock objects in your tests have the same api as the objects they are replacing, you can use auto-speccing.