[英]Django UnitTest with Mock
I am writing an Unit-Test for a Django class-based view. 我正在为基于Django类的视图编写单元测试。
class ExampleView(ListView):
def get_context_data(self, **kwargs):
context = super(EampleView, self).get_context_data(**kwargs)
## do something else
def get_queryset(self, **kwargs):
return self.get_data()
def get_data(self):
call_external_API()
## do something else
The key issue is that call_external_API()
in get_data()
. 关键问题是
get_data()
中的call_external_API()
get_data()
。
When I am writing Unit-test, I don't really want to call external API to get data. 在编写单元测试时,我真的不想调用外部API来获取数据。 First, that will cost my money;
首先,这将花费我的钱; second, I can easily test that API in another test file.
其次,我可以轻松地在另一个测试文件中测试该API。
I also can easily test this get_data()
method by having an unit-test only for it and mock the output of call_external_API()
. 我也可以通过仅对其进行单元测试并模拟
call_external_API()
的输出来轻松测试此get_data()
方法。
However, when I test this whole class-based view, I simply will do 但是,当我测试整个基于类的视图时,我只会做
self.client.get('/example/url/')
and check the status code and context data to verify it. 并检查状态码和上下文数据以进行验证。
In this case, how do I mock this call_external_API()
when I am testing the whole class-based view? 在这种情况下,当我测试整个基于类的视图时,如何模拟此
call_external_API()
?
What your are looking for is patch
from unittest.mock
. 您正在寻找的是
unittest.mock
patch
。 You can patch call_external_api()
by a MagicMock()
object. 您可以通过
MagicMock()
对象修补call_external_api()
。
Maybe you want to patch call_external_api()
for all your tests in class. 也许您想为类中的所有测试修补
call_external_api()
。 patch
give to you essentialy two way to do it patch
为您提供了两种必备的方法
start()
and stop()
in setUp()
and tearDown()
respectively setUp()
和tearDown()
使用start()
和stop()
Decorate a class by patch
decorator is like decorate all test methods (see documentation for details) and the implementation will be very neat. 用
patch
装饰器装饰类就像装饰所有测试方法(有关详细信息,请参见文档),实现将非常简洁。 Follow example assume that your view is in my_view
module. 以下示例假定您的视图位于
my_view
模块中。
@patch("my_view.call_external_api", autospec=True)
class MyTest(unittest.TestCase):
def setUp(self):
self.client = Client()
def test_get_data(self, mock_call_external_api):
self.client.get('/example/url/')
self.assertTrue(mock_call_external_api.called)
More sophisticate examples can be build and you can check how you call mock_call_external_api
and set return value or side effects for your API. 可以构建更多复杂的示例,并且可以检查如何调用
mock_call_external_api
并设置API的返回值或副作用。
I don't give any example about start and stop way to do it (I don't really like it) but I would like to spend some time on two details : 我没有提供任何有关启动和停止方式的示例(我不太喜欢),但是我想花一些时间在两个细节上 :
my_view
module you define call_external_api
or you import it by from my_API_module import call_external_api
otherwise you should pay some attention on Where to patch my_view
模块中定义了call_external_api
或者通过from my_API_module import call_external_api
导入了它,否则您应该注意在哪里打补丁 autospec=True
: IMHO it should be used in every patch call and documentation explain why very well autospec=True
:恕我直言,应该在每个补丁程序调用中使用它, 文档说明了为什么很好 You can mock the call_external_api()
method when testing the classed based view with something like this: 在测试基于分类的视图时,可以使用
call_external_api()
方法模拟call_external_api()
方法:
import modulea
import unittest
from mock import Mock
class ExampleTestCase(unittest.TestCase):
def setUp(self):
self.call_external_api = modulea.call_external_api
def tearDown(self):
modulea.call_external_api = self.call_external_api
def get_data(self):
modulea.call_external_api = Mock(return_value="foobar")
modulea.call_external_api()
## do something else
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.