При использовании unittest.mock ответ должен быть импортирован или высмеян
Я учусь unittest и unittest.mock, причем последнее не совсем понятно.
Я издеваюсь над ответом конечной точки и столкнулся со следующим:
import unittest
from unittest.mock import patch
from rest_framework.test import APIClient
class CoreTestCase(unittest.TestCase):
@patch('core.views.CoreViewSet.list')
def test_response(self, mock_get):
mock_get.return_value = [{'hello': 'world'}]
client = APIClient()
response = client.get('/core/')
print(response.data)
Что привело к следующей ошибке:
AssertionError: Expected a `Response`, `HttpResponse` or `HttpStreamingResponse` to be returned from the view, but received a `<class 'list'>`
Имеет смысл, потому что DRF использует Response.
Чтобы обойти ошибку, я изменил формулировку на:
import unittest
from unittest.mock import patch
from rest_framework.test import APIClient
from rest_framework.response import Response
class CoreTestCase(unittest.TestCase):
@patch('core.views.CoreViewSet.list')
def test_response(self, mock_get):
mock_get.return_value = Response([{'hello': 'world'}])
client = APIClient()
response = client.get('/core/')
print(response.data)
Что достигло желаемого результата, и я просто передавал массив объектов (или список dicts).
Однако я не уверен, что это был правильный способ и что вместо него следовало использовать Mock(). Могу честно сказать, что я не смог понять, как правильно использовать Mock() или MagicMock(), или найти учебник, в котором это четко объясняется, поэтому мои попытки использовать его с:
mock_get.return_value = Mock([{'hello': 'world'}])
В результате:
TypeError: 'module' object is not callable
Есть предложения о том, как следует реализовать этот тест?
Причина
AssertionError: Ожидалось, что из представления будет возвращено
Response,HttpResponseилиHttpStreamingResponse, но получено<class 'list'>
Эта ошибка происходит из утверждения isinstance здесь.
Решение
Если вы хотите использовать Mock или MagicMock для имитации Response и прохождения isinstance проверки, вы можете использовать spec или spec_set параметр при создании имитации ответа.
class CoreTestCase(unittest.TestCase):
@patch('core.views.CoreViewSet.list')
def test_response(self, mock_get):
mock_get.return_value = Mock(spec=Response, data=[{'hello': 'world'}])
...
Примечания
При создании Mock или Magic, вы должны передать имя свойства того, что вы хотите высмеять, в качестве аргументов ключевого слова. В данном случае вы хотите поиздеваться над Response.data, поэтому вам следует установить Mock(data=<DATA_VALUE>). В противном случае значение будет передано в позиционные аргументы Mock.
Официальная документация по python также содержит четкие примеры использования mock модуля здесь.