Mocking an external API call in a Django view test
Question:
I have written a view in Django that receives text from the user and calls an external API for that text to be translated.
View function:
def translate_view(request):
if request.method == 'POST':
form = InputForm(request.POST)
if form.is_valid():
source_lang = form.cleaned_data["source_lang"]
target_lang = form.cleaned_data["target_lang"]
source_text = form.cleaned_data["source_text"]
deepl_result = call_deepl_api(source_text, source_lang, target_lang)
return render(
request,
"output.html",
{
"source_lang": source_lang,
"target_lang": target_lang,
"source_text": source_text,
"deepl_result": deepl_result,
},
)
else:
form = InputForm()
return render(request, 'input.html', {'form': form})
I would like to test this view, and I think I have made the beginner’s mistake of actually calling the API in my tests (they are very slow). As far as I understand it looks like I should mock the external API call, but I am struggling to understand how to do this. Could somebody teach me how to do this for the above view? Any help would be much appreciated!
Tests:
class TestOutput(SimpleTestCase):
def setUp(self):
self.valid_data_response = self.client.post(
reverse('home'),
{'direction': 'Ja>En', 'source_text': '花粉飛散情報',}
)
def test_output_page_status_code_with_valid_data(self):
self.assertEqual(self.valid_data_response.status_code, 200)
... more tests
Answers:
In case this is useful to anyone else, I was able to solve this with the following.
Here, the views.py file contains the view function "translate_view()" shown in the question, and also a "call_deepl_api()" utility/helper function. Below, the call_deepl_api() function is mocked.
from unittest.mock import patch
class TestOutput(SimpleTestCase):
def setUp(self):
with patch('your_app.views.call_deepl_api') as mock_deepl_call:
deepl_result, deepl_usage = 'Pollen dispersal information', 6
mock_deepl_call.return_value = deepl_result, deepl_usage
self.response = self.client.post(
reverse('home'),
{'direction': 'Ja>En', 'source_text': '花粉飛散情報'}
)
# Assert that mocked function is actually called.
mock_deepl_call.assert_called_once()
def test_output_page_response_status_code(self):
self.assertEqual(self.response.status_code, 200)
... more tests
I have written a view in Django that receives text from the user and calls an external API for that text to be translated.
View function:
def translate_view(request):
if request.method == 'POST':
form = InputForm(request.POST)
if form.is_valid():
source_lang = form.cleaned_data["source_lang"]
target_lang = form.cleaned_data["target_lang"]
source_text = form.cleaned_data["source_text"]
deepl_result = call_deepl_api(source_text, source_lang, target_lang)
return render(
request,
"output.html",
{
"source_lang": source_lang,
"target_lang": target_lang,
"source_text": source_text,
"deepl_result": deepl_result,
},
)
else:
form = InputForm()
return render(request, 'input.html', {'form': form})
I would like to test this view, and I think I have made the beginner’s mistake of actually calling the API in my tests (they are very slow). As far as I understand it looks like I should mock the external API call, but I am struggling to understand how to do this. Could somebody teach me how to do this for the above view? Any help would be much appreciated!
Tests:
class TestOutput(SimpleTestCase):
def setUp(self):
self.valid_data_response = self.client.post(
reverse('home'),
{'direction': 'Ja>En', 'source_text': '花粉飛散情報',}
)
def test_output_page_status_code_with_valid_data(self):
self.assertEqual(self.valid_data_response.status_code, 200)
... more tests
In case this is useful to anyone else, I was able to solve this with the following.
Here, the views.py file contains the view function "translate_view()" shown in the question, and also a "call_deepl_api()" utility/helper function. Below, the call_deepl_api() function is mocked.
from unittest.mock import patch
class TestOutput(SimpleTestCase):
def setUp(self):
with patch('your_app.views.call_deepl_api') as mock_deepl_call:
deepl_result, deepl_usage = 'Pollen dispersal information', 6
mock_deepl_call.return_value = deepl_result, deepl_usage
self.response = self.client.post(
reverse('home'),
{'direction': 'Ja>En', 'source_text': '花粉飛散情報'}
)
# Assert that mocked function is actually called.
mock_deepl_call.assert_called_once()
def test_output_page_response_status_code(self):
self.assertEqual(self.response.status_code, 200)
... more tests