我有一個夾具,像這樣模擬一個外部庫,使用pytest-mock,它是unittest.mock的一個包裝器。
# client.py
import Test as TestLibrary
class LibraryName()。
def get_client()。
return TestLibrary.Library()
# library_service.py
def using_library() 。
'''
編輯注:Library().attribute在幕后被設定為
self.attribute = Attribute()
所以這可能會影響嘲諷的效果
'''
client = LibraryName.get_client()
return client.attribute.method()
# conftest.py
@pytest.fixture
def library_client_mock(mocker)。
import測驗 as TestLibrary
return mocker.patch.object(TestLibrary, 'Library' )
# test_library_service.py
def test_library_method(library_client_mock)。
結果 = using_library()
我可以這樣模擬一個回傳值:
我可以這樣模擬一個回傳值。
def test_library_method(library_client_mock)。
library_client_mock.return_value.attribute.return_value.method.return_value = "test"。
結果 = using_library()
assert 結果 == "test"
但是我不能用side_effect來模擬拋出一個例外
def test_library_method(library_client_mock)。
library_client_mock.return_value.attribute.return_value.method.side_effect = TypeError # does not work。
library_client_mock.return_value.attribute.return_value.method.side_effect = TypeError() # 不起作用。
attrs = { ' attribute.method.side_effect': TypeError }
library_client_mock.configure_mock(**attrs) # doesn't work[/span
with pytest.raises(TypeError)。
using_library() # fails assertion。
我在這里錯過了什么?
uj5u.com熱心網友回復:
這些是你的代碼中的錯誤:
你的代碼中存在以下錯誤:
你的代碼中存在以下錯誤
改變:
library_client_mock.return_value.attribute.return_value.method.return_value = "test"/span>
致:
library_client_mock.return_value.attribute.method.return_value = "test"
改變:
library_client_mock.return_value.attribute.return_value.method.side_effect = TypeError
致:
library_client_mock.return_value. attribute.method.side_effect = TypeError
解釋
.return_value必須只用于可呼叫的物件,例如一個函式,如documented:
return_value將此設定為配置通過呼叫mock回傳的值:
>>> mock = Mock() >>> mock.return_value = 'fish'/span> >>> mock() 'fish'
因此,你只能在以下情況下使用.return_value:
TestLibrary.Library()TestLibrary.Library().attribute.method()。
但不包括:
TestLibrary.Library().attribute。
因為.attribute不是一個可呼叫的,例如TestLibrary.Library().attribute()。
警告
你修補Library的方式是通過它的源位置Test.Library(或別名為TestLibrary.Library)。具體通過:
import Test as TestLibrary
return mocker.patch.object(TestLibrary, 'Library' )
目前它是有效的,因為你匯入和使用它的方式是通過根路徑。
# client.py。
import Test as TestLibrary
...
return TestLibrary.Library()
...
但是如果我們改變匯入該庫的方式,并匯入一個本地版本到client.py:
# client.py。
from Test import Library # Instead of <import Test as TestLibrary>
...
return Library() # Instead of <TestLibrary.Library()>
...
現在它將失敗。理想情況下,你應該修補被測系統使用的具體名稱,這里是client.Library。
import client
return mocker.patch.object(client, 'Library')
除非你確定所有將使用該庫的檔案將只匯入根目錄而不是本地版本。
uj5u.com熱心網友回復:
@Niel Godfrey Ponciano用這個語法為side_effect
library_client_mock.return_value. attribute.method.side_effect = TypeError
但這還不夠。
在
# conftest.py
@pytest.fixture
def library_client_mock(mocker)。
import測驗 as TestLibrary
return mocker.patch.object(TestLibrary, 'Library' )
我不得不添加一個額外的模擬:
我不得不添加一個額外的模擬。
# conftest.py。
@pytest.fixture
def library_client_mock(mocker)。
import Test as TestLibrary
mock_library_client = mocker.patch.object(TestLibrary, 'Library')
#選項1
mock_attribute = Mock()
# option 2, path to Library.attribute = Attribute()
mock_attribute = mocker.patch.object(TestLibrary.services, 'Attribute', autospec=True)
mock_library_client.attach_mock(mock_attribute, "屬性")
return mock_library_client
然后下面的兩個陳述句都按預期作業。雖然我不確定為什么return_value在沒有附加mock的情況下可以開箱作業,但side_effect卻不能。
# return_value設定正確。
# NOTE return_value needed after each
library_client_mock.return_value.attribute.return_value.method.return_value = "test"。
# side_effect設定正確。
# NOTE return_value不需要在 "屬性 "之后。
library_client_mock.return_value.attribute.method.side_effect = TypeError
轉載請註明出處,本文鏈接:https://www.uj5u.com/shujuku/310298.html
標籤:
上一篇:在Jest中為單元測驗模擬這個NodeJSKubernetes客戶端的最佳方法?
下一篇:使用jest模擬外部庫呼叫
