How to write tests for an External API call?

Asked

Viewed 56 times

3

I am researching about Unit Testing and TDD and wanted to apply this to some scripts I have developed. The issue is that these scripts create data on an external service by calling API methods, for example:

project = sdk.create_project(body=models.WriteProject(
                                    name="test-project"))

When running a test that calls this method, it would be created really a new project? It is possible to test the call but not to complete, in fact, the creation of the object?

It is a more conceptual doubt, but if necessary to exemplify, I am working with Python.

  • 2

    Yes, it is possible. You can search for mock.

  • 1

    @Leila recommend this book that just came out of Alessandro Molina’s oven is sensational (mainly because you are using Python): https://www.packtpub.com/product/crafting-test-driven-software-with-python/9781838642655 In practice, install Postman, create an account there and create a MOCK server (which SIMULATES, API responses - to be straight to the point is a garnish server that returns outputs that you should configure) is a quick and easy suggestion for you to simulate the response behavior of an API. I use a lot and recommend

  • @Matthew thanks, the book looks good, I’ll research more on

1 answer

2


You should not test the external API as it is out of your control. What you should test is what your code does, given the behavior(s) that the external API may display.

For example, let’s say that its function get_project creates and returns an object created by the external API. You know that if the wrong parameters are passed, the API will launch an exception of the type SomeExternalAPIException. Then you write your code to handle it using a Try/except, and returning None in case of error:

import api_externa

def get_project(
    params: Dict[str, Any],
) -> Optional[api_externa.Project]:
    """
    Cria um projeto novo usando a API externa e o retorna.
    Pode retornar None caso parâmetros inválidos sejam 
    passados para a API externa.
    """
    try:
        project = api_externa.create_project(params=params)
        return project
    except SomeExternalAPIException:
        return None

In your test, you don’t need to test whether the API works as you expect (this is the function of the API developers). You test only if your code actually returns the API object when knowingly valid parameters are delivered to it, and if it returns None otherwise:

import unittest

import api_externa

from myapp import get_project

class TestMyApp(unittest.TestCase):

    def test_get_project_returns_a_project_when_params_are_valid(self):
        """
        Testa se a função get_project retorna uma instância de 
        api_externa.Project quando são passados parâmetros válidos 
        a ela
        """
        params = { ... }  # parâmetros válidos aqui
        returned_value = get_project(params=params)
        self.assertIsInstance(returned_value, api_externa.Project)

    def test_get_project_returns_none_when_params_are_invalid(self):
        """
        Testa se a função get_project retorna None
        quando são passados parâmetros inválidos a ela
        """
        params = { ... }  # parâmetros inválidos aqui
        returned_value = get_project(params=params)
        self.assertIsNone(returned_value)


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

If you need control/simulate some aspect of the external API (for example, the API connects to the web to access some data, and you need to simulate a drop in connection for one of the tests), then you need to use mocks, which are a way to create arbitrary objects that replace any element of the Api during a test. In this case, I suggest starting by reading the python documentation for mocks.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.