[英]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.