[Django]-Unittest Django: Mock external API, what is proper way?

22👍

You should mock the direct collaborators of the code under test. For Book that would be utils. For utils that would be requests.

So for the BookModelTestCase:

class BookModelTestCase(TestCase):

    @mock.patch('app.models.utils')
    def test_save_book_calls_google_api(self, mock_utils):
        mock_utils.get_original_title_and_name.return_value = {
            'title': 'Google title',
            'author': 'Google author'
        }

        book = Book(
            title='Some title',
            isbn='12345'
        )
        book.save()

        self.assertEqual(book.title, 'Google title')
        self.assertEqual(book.author, 'Google author')
        mock_utils.get_original_title_and_name.assert_called_once_with('12345')

And then you can create a separate test case to test get_original_title_and_name:

class GetOriginalTitleAndNameTestCase(TestCase):

    @mock.patch('app.utils.requests.get')
    def test_get_original_title_and_name_from_google_api(self, mock_get):
        mock_response = mock.Mock()
        # Define response data from Google API
        expected_dict = {
            'kind': 'books#volumes',
            'totalItems': 1,
            'items': [
                {
                    'kind': 'books#volume',
                    'id': 'IHxXBAAAQBAJ',
                    'etag': 'B3N9X8vAMWg',
                    'selfLink': 'https://www.googleapis.com/books/v1/volumes/IHxXBAAAQBAJ',
                    'volumeInfo': {
                        'title': "Alice's Adventures in Wonderland",
                        'authors': [
                            'Lewis Carroll'
                        ]
                    }
                }
                    ]
            }

        # Define response data for my Mock object
        mock_response.json.return_value = expected_dict
        mock_response.status_code = 200

        # Define response for the fake API
        mock_get.return_value = mock_response

        # Call the function
        result = get_original_title_and_name(12345)

        self.assertEqual(result, {
            'title': "Alice's Adventures in Wonderland", 
            'author': 'Lewis Carroll'
        })
        mock_get.assert_called_once_with(GOOGLE_API_URL, params={
            'key': GOOGLE_API_KEY,
            'q': 'isbn:12345',
            'printType': 'books',
        })

Leave a comment