2015-07-29 8 views
17

समस्या
एक वर्ग उस वर्ग के उदाहरणों की विशेषताओं संरक्षण नहीं है पैच करने के लिए autospec=True साथ mock.patch का उपयोग करना "AttributeError नकली वस्तु कोई गुण नहीं है"।एक वर्ग पैदावार पैचिंग: जब उदाहरण तक पहुँचने का श्रेय

विवरण
मैं एक वर्ग Bar कि एक Bar वस्तु विशेषता के रूप में वर्ग Foo का एक उदाहरण को दर्शाता है परीक्षण करने के लिए कोशिश कर रहा हूँ foo कहा जाता है। परीक्षण के तहत Bar विधि bar कहा जाता है; यह Foo उदाहरण Bar से संबंधित विधि foo पर कॉल करता है। इस परीक्षण में, मैं Foo मजाक कर रहा हूँ, के रूप में मैं केवल परीक्षण करने के लिए है कि Bar सही Foo सदस्य तक पहुँच रहा है चाहता हूँ:

import unittest 
from mock import patch 

class Foo(object): 
    def __init__(self): 
     self.foo = 'foo' 

class Bar(object): 
    def __init__(self): 
     self.foo = Foo() 

    def bar(self): 
     return self.foo.foo 

class TestBar(unittest.TestCase): 
    @patch('foo.Foo', autospec=True) 
    def test_patched(self, mock_Foo): 
     Bar().bar() 

    def test_unpatched(self): 
     assert Bar().bar() == 'foo' 

वर्गों और तरीकों ठीक (test_unpatched गुजरता) काम करते हैं, लेकिन जब मैं में फू करने की कोशिश एक टेस्ट केस autospec=True का उपयोग कर (दोनों nosetests और pytest का उपयोग कर परीक्षण किया गया), मैं का सामना "AttributeError: नकली वस्तु कोई गुण नहीं है 'foo'"

19:39 $ nosetests -sv foo.py 
test_patched (foo.TestBar) ... ERROR 
test_unpatched (foo.TestBar) ... ok 

====================================================================== 
ERROR: test_patched (foo.TestBar) 
---------------------------------------------------------------------- 
Traceback (most recent call last): 
    File "/usr/local/lib/python2.7/dist-packages/mock.py", line 1201, in patched 
    return func(*args, **keywargs) 
    File "/home/vagrant/dev/constellation/test/foo.py", line 19, in test_patched 
    Bar().bar() 
    File "/home/vagrant/dev/constellation/test/foo.py", line 14, in bar 
    return self.foo.foo 
    File "/usr/local/lib/python2.7/dist-packages/mock.py", line 658, in __getattr__ 
    raise AttributeError("Mock object has no attribute %r" % name) 
AttributeError: Mock object has no attribute 'foo' 

दरअसल, जब मैं mock_Foo.return_value.__dict__ प्रिंट आउट, मैं देख सकता हूँ कि foo नहीं है बच्चों की सूची में या तरीकों:

{'_mock_call_args': None, 
'_mock_call_args_list': [], 
'_mock_call_count': 0, 
'_mock_called': False, 
'_mock_children': {}, 
'_mock_delegate': None, 
'_mock_methods': ['__class__', 
        '__delattr__', 
        '__dict__', 
        '__doc__', 
        '__format__', 
        '__getattribute__', 
        '__hash__', 
        '__init__', 
        '__module__', 
        '__new__', 
        '__reduce__', 
        '__reduce_ex__', 
        '__repr__', 
        '__setattr__', 
        '__sizeof__', 
        '__str__', 
        '__subclasshook__', 
        '__weakref__'], 
'_mock_mock_calls': [], 
'_mock_name': '()', 
'_mock_new_name': '()', 
'_mock_new_parent': <MagicMock name='Foo' spec='Foo' id='38485392'>, 
'_mock_parent': <MagicMock name='Foo' spec='Foo' id='38485392'>, 
'_mock_wraps': None, 
'_spec_class': <class 'foo.Foo'>, 
'_spec_set': None, 
'method_calls': []} 

autospec की मेरी समझ है कि, अगर यह सच है, पैच चश्मा रिकर्सिवली लागू करना चाहिए। चूंकि foo वास्तव में फू उदाहरणों की विशेषता है, क्या इसे पैच नहीं किया जाना चाहिए? यदि नहीं, तो मैं फू उदाहरणों के गुणों को संरक्षित करने के लिए फू मॉक कैसे प्राप्त करूं?

नोट:
यह एक तुच्छ उदाहरण है कि मूल समस्या से पता चलता है। हकीकत में, मैं एक थर्ड पार्टी मॉड्यूल का मज़ाक उड़ा रहा हूं। क्लास - consul.Consul - जिसका ग्राहक मैं अपने पास एक कंसुल रैपर वर्ग में तत्काल हूं। चूंकि मैं कंसुल मॉड्यूल को बनाए नहीं रखता, इसलिए मैं अपने परीक्षणों के अनुरूप स्रोत को संशोधित नहीं कर सकता (मैं वास्तव में वैसे भी ऐसा नहीं करना चाहता)। इसके लायक होने के लिए, consul.Consul() एक कंसुल क्लाइंट लौटाता है, जिसमें kv विशेषता है - consul.Consul.KV का एक उदाहरण। kv में एक विधि get है, जिसे मैं अपने कंसुल क्लास में एक उदाहरण विधि get_key में लपेट रहा हूं। consul.Consul पैच करने के बाद, AttributeError की वजह से विफल होने के लिए कॉल: मॉक ऑब्जेक्ट में कोई विशेषता kv नहीं है।

संसाधन पहले से ही जांचा गया:

http://mock.readthedocs.org/en/latest/helpers.html#autospeccing http://mock.readthedocs.org/en/latest/patch.html

+1

उस वर्ग के उदाहरण बनाने के लिए नकली की आवश्यकता होगी। यह कभी भी एक अच्छा विचार नहीं है, क्योंकि इसे उस कोड को निष्पादित करने की आवश्यकता होगी जिसे आप पहली जगह में नकली के साथ बदलने की कोशिश कर रहे थे। –

उत्तर

24

नहीं है, autospeccing बाहर नकली नहीं कर सकते विशेषताओं मूल वर्ग (या किसी अन्य विधि में) की __init__ विधि में निर्धारित किया है। यह केवल स्थिर गुण, वर्ग पर पाया जा सकता है कि सब कुछ नकल कर सकते हैं।

अन्यथा, नकली को उस वर्ग का एक उदाहरण बनाना होगा जिसे आपने पहली जगह में नकली के साथ बदलने की कोशिश की थी, जो एक अच्छा विचार नहीं है (सोचने वाले वर्ग जो तुरंत वास्तविक संसाधन बनाते हैं)।

एक ऑटो-स्क्वाड मॉक की पुनरावर्ती प्रकृति तब उन स्थिर विशेषताओं तक सीमित है; यदि foo एक क्लास विशेषता है, तो Foo().foo तक पहुंच उस विशेषता के लिए एक ऑटो-स्क्वाड मॉक वापस कर देगी। यदि आपके पास कक्षा Spam है जिसका eggs विशेषता Ham प्रकार का ऑब्जेक्ट है, तो Spam.eggs का मॉक Ham वर्ग का एक ऑटो-स्क्वाड मॉक होगा।

A more serious problem is that it is common for instance attributes to be created in the __init__ method and not to exist on the class at all. autospec can’t know about any dynamically created attributes and restricts the api to visible attributes.

तुम बस स्थापित करना चाहिए लापता खुद जिम्मेदार बताते हैं:

@patch('foo.Foo', autospec=TestFoo) 
def test_patched(self, mock_Foo): 
    mock_Foo.return_value.foo = 'foo' 
    Bar().bar() 

या परीक्षण प्रयोजनों कि कहते हैं के लिए अपने Foo वर्ग का एक उपवर्ग बनाने

documentation you readस्पष्ट इस को शामिल किया गया कक्षा विशेषता के रूप में विशेषता:

class TestFoo(foo.Foo): 
    foo = 'foo' # class attribute 

@patch('foo.Foo', autospec=TestFoo) 
def test_patched(self, mock_Foo): 
    Bar().bar() 
+1

हाँ, सुनिश्चित नहीं है कि मैं इसे कैसे चूक गया। यह बहुत स्पष्ट था। मुझे लगता है कि मुझे यही करना होगा। मैं इससे बचने की उम्मीद कर रहा था ताकि परीक्षण कंसुल कक्षा के उचित उपयोग को सत्यापित करेगा। मुझे लगता है कि मुझे इसके लिए भारी हाथ एकीकरण परीक्षणों पर भरोसा करना होगा। – Clandestine

संबंधित मुद्दे