使用 unittest.mock 时应该导入还是模拟 Response
Should Response be imported or mocked when using 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)
这达到了预期的结果,我只是传入了一个对象数组(或字典列表)。
但是,我不确定这是处理此问题的正确方法,以及是否应该使用 Mock()
。老实说,我一直无法弄清楚如何正确使用 Mock()
或 MagicMock()
,或者找不到解释清楚的教程,所以我尝试使用它:
mock_get.return_value = Mock([{'hello': 'world'}])
刚刚导致:
TypeError: 'module' object is not callable
关于如何实施这个测试有什么建议吗?
原因
AssertionError: Expected a Response
, HttpResponse
or HttpStreamingResponse
to be returned from the view, but received a <class 'list'>
此错误来自 isinstance
断言 here。
解决方案
如果你想用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
模块的清晰示例 here。
我正在学习 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)
这达到了预期的结果,我只是传入了一个对象数组(或字典列表)。
但是,我不确定这是处理此问题的正确方法,以及是否应该使用 Mock()
。老实说,我一直无法弄清楚如何正确使用 Mock()
或 MagicMock()
,或者找不到解释清楚的教程,所以我尝试使用它:
mock_get.return_value = Mock([{'hello': 'world'}])
刚刚导致:
TypeError: 'module' object is not callable
关于如何实施这个测试有什么建议吗?
原因
AssertionError: Expected a
Response
,HttpResponse
orHttpStreamingResponse
to be returned from the view, but received a<class 'list'>
此错误来自 isinstance
断言 here。
解决方案
如果你想用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
模块的清晰示例 here。