[英]How to set “return_value” once for TestCase. Python. Django
这是示例测试:
import a
import b
import c
import mock
from django.test import TestCase
@mock.patch.object(a, "method_a")
@mock.patch.object(b, "method_b")
@mock.patch.object(c, "method_c")
class SomeTestCase(TestCase):
def setUp(self):
# I want to set mock_method_a.return_value = 1 once here (or not here, but once)
pass
def test_one(self, mock_method_a, mock_method_b, mock_method_c):
mock_method_a.return_value = 1
mock_method_b.return_value = 2
pass # some test stuff
def test_two(self, mock_method_a, mock_method_b, mock_method_c):
mock_method_a.return_value = 1
mock_method_b.return_value = 2
pass # some test stuff
def test_three(self, mock_method_a, mock_method_b, mock_method_c):
mock_method_a.return_value = 1
mock_method_b.return_value = 2
pass # some test stuff
奎斯顿 :
如何避免在TestCase中的每个测试中设置“return_value”的重复代码?
我期待“setUp”方法或类似的东西。
可能吗?
PS:模拟版本模拟== 1.3.0,django版本Django == 1.8.4
您可以在@mock.patch.object()
装饰器中设置return_value
:
@mock.patch.object(c, "method_c", return_value=3)
@mock.patch.object(b, "method_b", return_value=2)
@mock.patch.object(a, "method_a", return_value=1)
class SomeTestCase(TestCase):
def test_one(self, mock_method_a, mock_method_b, mock_method_c):
# do test stuff, return values have been set
def test_two(self, mock_method_a, mock_method_b, mock_method_c):
# do test stuff, return values have been set
def test_three(self, mock_method_a, mock_method_b, mock_method_c):
# do test stuff, return values have been set
(注意:使用@mock.patch
进行装饰时,装饰器从底部开始应用,因此mock_method_a
作为第一个参数传入,需要将装饰器放在最接近类定义的位置)。
mock.patch.object()
的return_value
关键字参数传递给MagicMock()
构造函数。 请参阅mock.patch.object()
文档 :
与
patch()
一样,patch.object()
接受任意关键字参数来配置它创建的模拟对象。
和mock.Mock
文档 :
Mock
采用几个可选参数来指定Mock
对象的行为:
[...]
return_value
:调用mock时返回的值。 默认情况下,这是一个新的Mock
(在第一次访问时创建)。 请参阅return_value
属性。
如果您还想避免在测试用例之外设置模拟或者不喜欢每个测试函数的附加参数,那么您也可以在setUp
方法中创建修补程序 ,然后在测试结束时再次删除它们通过unittest.TestCase.addCleanup()
方法注册回调。
通过调用patcher.start()
方法为每个测试应用patcher.start()
,该方法返回新的模拟对象:
class SomeTestCase(TestCase):
def setUp(self):
patcher_method_a = mock.patch.object(a, "method_a")
self.mock_method_a = patcher_method_a.start()
self.mock_method_a.return_value = 1
patcher_method_b = mock.patch.object(b, "method_b")
self.mock_method_b = patcher_method_b.start()
self.mock_method_b.return_value = 2
patcher_method_c = mock.patch.object(c, "method_c")
self.mock_method_c = patcher_method_c.start()
self.mock_method_c.return_value = 3
# when the test is done, stop **all** patchers
self.addCleanup(mock.patch.stopall)
def test_one(self):
# use self.mock_method_a, etc.
def test_two(self, mock_method_a, mock_method_b, mock_method_c):
# use self.mock_method_a, etc.
def test_three(self, mock_method_a, mock_method_b, mock_method_c):
# use self.mock_method_a, etc.
请注意, mock.patch.stopall()
方法将停止所有已启动的模拟修补程序 。 您还可以传递每个.stop
属性:
self.addCleanup(patcher_method_a.stop)
self.addCleanup(patcher_method_b.stop)
self.addCleanup(patcher_method_c.stop)
如果你必须创建很多这样的设置,你可以创建一个帮助函数来处理重复的部分:
def setup_object_patch(testcase, object, target, return_value, attrname=None):
patcher = mock.patch.object(object, target)
mock = patcher.start()
mock.return_value = return_value
setattr(testcase, attrname or f'mock_{target}', mock)
testcase.addCleanup(patcher.stop)
并且可能在映射循环中使用它:
def setUp(self):
mocks = {
# attribute name on test -> object, target, return_value
'mock_method_a': (a, 'method_a', 1),
'mock_method_b': (b, 'method_b', 2),
'mock_method_c': (c, 'method_c', 3),
}
for attrname, params in mocks.items():
setup_object_patch(*params, attrname=attrname)
TestCase.setUp()
方法中的patcher.start()
方法使得继承更容易,其中基本测试用例用作所有使用相同共享模拟设置的几个测试用例的基础。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.