मैं मोक्स के साथ निम्नलिखित कोड का परीक्षण कैसे कर सकता हूं (मॉक का उपयोग करके, माइकल फ़ॉर्ड्स की रूपरेखा द्वारा पैच डेकोरेटर और प्रहरी ):
def testme(filepath):
with open(filepath, 'r') as f:
return f.read()
मैं मोक्स के साथ निम्नलिखित कोड का परीक्षण कैसे कर सकता हूं (मॉक का उपयोग करके, माइकल फ़ॉर्ड्स की रूपरेखा द्वारा पैच डेकोरेटर और प्रहरी ):
def testme(filepath):
with open(filepath, 'r') as f:
return f.read()
जवाबों:
इसे करने का तरीका मॉक 0.7.0 में बदल गया है जो अंत में पायथन प्रोटोकॉल विधियों (जादू के तरीकों) का समर्थन करता है, विशेष रूप से मैजिकमॉक का उपयोग करते हुए:
http://www.voidspace.org.uk/python/mock/magicmock.html
प्रसंग प्रबंधक के रूप में खुले हुए मॉकिंग का एक उदाहरण (नकली दस्तावेज़ में उदाहरण पृष्ठ से):
>>> open_name = '%s.open' % __name__
>>> with patch(open_name, create=True) as mock_open:
... mock_open.return_value = MagicMock(spec=file)
...
... with open('/some/path', 'w') as f:
... f.write('something')
...
<mock.Mock object at 0x...>
>>> file_handle = mock_open.return_value.__enter__.return_value
>>> file_handle.write.assert_called_with('something')
__enter__और __exit__साथ ही साथ वस्तुओं को नकली करने के लिए है - क्या उत्तरार्द्ध दृष्टिकोण पुराना है, या अभी भी उपयोगी है?
fileचला गया है!
mock_openmockफ्रेमवर्क का हिस्सा है और उपयोग करने के लिए बहुत सरल है। patchसंदर्भ के रूप में उपयोग किए गए ऑब्जेक्ट को पैच को बदलने के लिए उपयोग किया जाता है: आप इसका उपयोग अपने परीक्षण को सरल बनाने के लिए कर सकते हैं।
के builtinsबजाय का उपयोग करें __builtin__।
from unittest.mock import patch, mock_open
with patch("builtins.open", mock_open(read_data="data")) as mock_file:
assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")
mockका हिस्सा नहीं है unittestऔर आपको पैच करना चाहिए__builtin__
from mock import patch, mock_open
with patch("__builtin__.open", mock_open(read_data="data")) as mock_file:
assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")
यदि आप patchडेकोरेटर के mock_open()रूप में परिणाम के new patchतर्क के रूप में उपयोग करेंगे तो तर्क थोड़ा अजीब हो सकता है।
इस मामले में new_callable patchतर्क का उपयोग करना बेहतर है और याद रखें कि प्रत्येक अतिरिक्त तर्क जो patchउपयोग नहीं new_callableकरता है, उसे patchप्रलेखन में वर्णित कार्य करने के लिए पारित किया जाएगा ।
पैच () मनमाना कीवर्ड तर्क लेता है। इन्हें निर्माण पर मॉक (या new_callable) में पारित किया जाएगा।
उदाहरण के लिए पायथन 3.x के लिए सजाया गया संस्करण है:
@patch("builtins.open", new_callable=mock_open, read_data="data")
def test_patch(mock_file):
assert open("path/to/open").read() == "data"
mock_file.assert_called_with("path/to/open")
याद रखें कि इस मामले patchमें आप परीक्षण समारोह के तर्क के रूप में नकली वस्तु जोड़ देंगे।
with patch("builtins.open", mock_open(read_data="data")) as mock_file:डेकोरेटर सिंटैक्स में परिवर्तित किया जा सकता है? मैंने कोशिश की है, लेकिन मुझे यकीन नहीं है कि मुझे @patch("builtins.open", ...) दूसरे तर्क के रूप में पारित करने की आवश्यकता है ।
return_valueकी mock_openएक और नकली वस्तु में और दूसरा नकली का ज़ोर return_value), लेकिन यह जोड़ कर काम mock_openके रूप में new_callable।
sixलगातार mockमॉड्यूल के लिए मॉड्यूल पर एक नज़र रखना । लेकिन मुझे नहीं पता कि यह builtinsएक सामान्य मॉड्यूल में भी है या नहीं।
नकली के नवीनतम संस्करणों के साथ, आप वास्तव में उपयोगी mock_open सहायक का उपयोग कर सकते हैं :
mock_open (नकली = कोई नहीं, read_data = कोई नहीं)
खुले के उपयोग को बदलने के लिए एक नकली बनाने के लिए एक सहायक कार्य करता है। यह खुले नाम से सीधे काम करता है या संदर्भ प्रबंधक के रूप में उपयोग किया जाता है।
मॉक तर्क कॉन्फ़िगर करने के लिए नकली वस्तु है। यदि कोई नहीं (डिफ़ॉल्ट) तो आपके लिए एक मैजिकमॉक बनाया जाएगा, जिसमें एपीआई मानक फ़ाइल हैंडल पर उपलब्ध विधियों या विशेषताओं तक सीमित है।
read_data फ़ाइल हैंडल के रीड मेथड के लिए एक स्ट्रिंग है जिसे वापस करना है। यह डिफ़ॉल्ट रूप से एक रिक्त स्ट्रिंग है।
>>> from mock import mock_open, patch
>>> m = mock_open()
>>> with patch('{}.open'.format(__name__), m, create=True):
... with open('foo', 'w') as h:
... h.write('some stuff')
>>> m.assert_called_once_with('foo', 'w')
>>> handle = m()
>>> handle.write.assert_called_once_with('some stuff')
.writeकॉल करते हैं, तो आप कैसे जांच करेंगे ?
handle.write.assert_any_call()। handle.write.call_args_listयदि ऑर्डर महत्वपूर्ण है तो आप प्रत्येक कॉल प्राप्त करने के लिए भी उपयोग कर सकते हैं ।
m.return_value.write.assert_called_once_with('some stuff')बेहतर है इमो। कॉल रजिस्टर करने से बचा जाता है।
Mock.call_args_listकिसी भी Mock.assert_xxxतरीके को कॉल करने की तुलना में मैन्युअल रूप से जोर देना सुरक्षित है । यदि आप मॉक की विशेषताओं में से किसी भी बाद में गलत वर्तनी करते हैं, तो वे हमेशा चुपचाप गुजरेंगे।
एक साधारण फ़ाइल के लिए mock_open का उपयोग करने के लिए read()( इस पृष्ठ पर पहले से दिए गए मूल mock_open स्निपेट को लिखने के लिए अधिक तैयार किया गया है):
my_text = "some text to return when read() is called on the file object"
mocked_open_function = mock.mock_open(read_data=my_text)
with mock.patch("__builtin__.open", mocked_open_function):
with open("any_string") as f:
print f.read()
मॉक_पेन के लिए डॉक्स के अनुसार ध्यान दें, यह विशेष रूप से है read(), इसलिए for line in fउदाहरण के लिए सामान्य पैटर्न के साथ काम नहीं करेगा ।
अजगर 2.6.6 / नकली 1.0.1 का उपयोग करता है
for line in opened_file:कोड के प्रकार के साथ काम नहीं कर सकता । मैंने पुनरावृत्ति करने वाले स्ट्रिंगरियो के साथ प्रयोग करने की कोशिश की, जो लागू होते हैं __iter__और इसके बजाय इसका उपयोग करते हैं my_text, लेकिन कोई भाग्य नहीं।
read()से आपके for line in opened_fileमामले में काम नहीं करेगा के लिए काम करता है; मैंने पोस्ट को स्पष्ट करने के लिए संपादित किया है
for line in f:समर्थन को इसके बजाय एक स्ट्रिंग ऑब्जेक्ट के open()रूप में रिटर्न मान का मजाक उड़ाकर प्राप्त किया जा सकता है ।
with open("any_string") as f: print f.read()
शीर्ष उत्तर उपयोगी है, लेकिन मैंने इस पर थोड़ा विस्तार किया।
यदि आप अपने फ़ाइल ऑब्जेक्ट का मान सेट करना चाहते हैं, तो इसके लिए यहां दिए गए तर्कों के आधार पर ( fइन as f) open()करें:
def save_arg_return_data(*args, **kwargs):
mm = MagicMock(spec=file)
mm.__enter__.return_value = do_something_with_data(*args, **kwargs)
return mm
m = MagicMock()
m.side_effect = save_arg_return_array_of_data
# if your open() call is in the file mymodule.animals
# use mymodule.animals as name_of_called_file
open_name = '%s.open' % name_of_called_file
with patch(open_name, m, create=True):
#do testing here
मूल रूप से, open()किसी ऑब्जेक्ट को वापस करेगा और उस ऑब्जेक्ट पर withकॉल करेगा __enter__()।
ठीक से मॉक करने के लिए, हमें open()मॉक ऑब्जेक्ट को वापस करने के लिए मॉक करना होगा । उस नकली वस्तु को उसके बाद उस __enter__()कॉल को मॉक करना चाहिए ( MagicMockजो हमारे लिए यह करेगा) उस नकली डेटा / फ़ाइल ऑब्जेक्ट को वापस करना होगा जिसे हम चाहते हैं (इसलिए mm.__enter__.return_value)। ऐसा करने से 2 मोक्स ऊपर के रास्ते से open()गुजरते हैं, जिससे हम पास किए गए तर्कों को कैप्चर कर सकते हैं और उन्हें हमारे do_something_with_dataतरीके से पास कर सकते हैं ।
मैंने एक स्ट्रिंग के रूप में एक पूरी मॉक फाइल पास की open()और मुझे do_something_with_dataइस तरह देखा:
def do_something_with_data(*args, **kwargs):
return args[0].split("\n")
यह स्ट्रिंग को एक सूची में बदल देता है ताकि आप एक सामान्य फ़ाइल के साथ निम्न कार्य कर सकें:
for line in file:
#do action
__enter__? यह निश्चित रूप से एक अनुशंसित तरीके से हैक की तरह दिखता है।
मुझे खेल में थोड़ी देर हो सकती है, लेकिन यह मेरे लिए तब काम करता है जब openएक नई फ़ाइल बनाने के बिना दूसरे मॉड्यूल में कॉल किया जाता है।
test.py
import unittest
from mock import Mock, patch, mock_open
from MyObj import MyObj
class TestObj(unittest.TestCase):
open_ = mock_open()
with patch.object(__builtin__, "open", open_):
ref = MyObj()
ref.save("myfile.txt")
assert open_.call_args_list == [call("myfile.txt", "wb")]
MyObj.py
class MyObj(object):
def save(self, filename):
with open(filename, "wb") as f:
f.write("sample text")
मेरे openअंदर __builtin__मॉड्यूल के अंदर फ़ंक्शन को पैच करके mock_open(), मैं बिना किसी को बनाए किसी फाइल को लिखने का मजाक उड़ा सकता हूं।
नोट: यदि आप एक ऐसे मॉड्यूल का उपयोग कर रहे हैं जो साइथॉन का उपयोग करता है, या आपका प्रोग्राम किसी भी तरह से साइथन पर निर्भर करता है, तो आपको अपनी फ़ाइल के शीर्ष पर शामिल करके साइथन के __builtin__मॉड्यूल को आयात करना होगा import __builtin__। __builtin__यदि आप साइथन का उपयोग कर रहे हैं तो आप सार्वभौमिक का मजाक नहीं उड़ा पाएंगे।
import __builtin__अपने परीक्षण मॉड्यूल में जोड़ना सुनिश्चित करने की आवश्यकता थी । इस लेख ने यह स्पष्ट करने में मदद की कि यह तकनीक क्यों काम करती है: ichimonji10.name/blog/6
यह एक पैच के लिए एक जॉन्सन कॉन्फिगर पढ़ने के लिए काम करता है।
class ObjectUnderTest:
def __init__(self, filename: str):
with open(filename, 'r') as f:
dict_content = json.load(f)
मॉक की गई वस्तु io.TextIOWrapper ऑब्जेक्ट ओपन () फ़ंक्शन द्वारा लौटाई गई है
@patch("<src.where.object.is.used>.open",
return_value=io.TextIOWrapper(io.BufferedReader(io.BytesIO(b'{"test_key": "test_value"}'))))
def test_object_function_under_test(self, mocker):
यदि आपको आगे किसी फ़ाइल की आवश्यकता नहीं है, तो आप परीक्षण विधि को सजा सकते हैं:
@patch('builtins.open', mock_open(read_data="data"))
def test_testme():
result = testeme()
assert result == "data"