2013-04-21 8 views
46

मैं समझना चाहता हूं कि आयातित मॉड्यूल से @patch एक फ़ंक्शन कैसे करें।पायथन एक आयातित मॉड्यूल से एक फ़ंक्शन मॉकिंग

यह वह जगह है जहां मैं अब तक हूं।

एप्लिकेशन/mocking.py:

from app.my_module import get_user_name 

def test_method(): 
    return get_user_name() 

if __name__ == "__main__": 
    print "Starting Program..." 
    test_method() 

एप्लिकेशन/my_module/__ init__.py:

def get_user_name(): 
    return "Unmocked User" 

परीक्षा/mock-test.py:

import unittest 
from app.mocking import test_method 

def mock_get_user(): 
    return "Mocked This Silly" 

@patch('app.my_module.get_user_name') 
class MockingTestTestCase(unittest.TestCase): 

    def test_mock_stubs(self, mock_method): 
    mock_method.return_value = 'Mocked This Silly') 
    ret = test_method() 
    self.assertEqual(ret, 'Mocked This Silly') 

if __name__ == '__main__': 
    unittest.main() 

यह काम करता है जैसा कि मैं अपेक्षा करता हूं। "पैच" मॉड्यूल बस get_user_name का अनमॉक मान देता है। मैं अन्य संकुलों से विधियों का नकल कैसे करूं जिन्हें मैं परीक्षण के तहत नामस्थान में आयात कर रहा हूं?

+1

सवाल "सर्वोत्तम प्रथाओं मजाक" के बारे में या या नहीं, तुम क्या कर रहे समझ में आता है है? पहले के बारे में मैं एक मॉकिंग लाइब्रेरी का उपयोग करना चाहूंगा जैसे कि ['मॉक'] (http://www.voidspace.org.uk/python/mock/), जिसे पायथन 3.3 + में शामिल किया गया है [' unittest .mock'] (http://docs.python.org/dev/library/unittest.mock)। – Bakuriu

+0

मैं पूछ रहा हूं कि क्या मैं इस अधिकार के बारे में जा रहा हूं। मैंने मॉक को देखा, लेकिन मुझे इस विशेष समस्या को हल करने का कोई तरीका नहीं दिख रहा है। क्या मैक में मैंने जो किया है उसे फिर से बनाने का कोई तरीका है? – nsfyn55

उत्तर

66

आप unittest.mock पैकेज से patch डेकोरेटर का उपयोग कर रहे जब आप नहीं नाम स्थान मॉड्यूल आप परीक्षण app.mocking.get_user_name के तहत नाम स्थान में यह पैचिंग कर रहे हैं (इस मामले app.my_module.get_user_name में) से आयात किया जाता पैचिंग कर रहे हैं।

from mock import patch 
from app.mocking import test_method 

class MockingTestTestCase(unittest.TestCase): 

    @patch('app.mocking.get_user_name') 
    def test_mock_stubs(self, test_patch): 
     test_patch.return_value = 'Mocked This Silly' 
     ret = test_method() 
     self.assertEqual(ret, 'Mocked This Silly') 

मानक पुस्तकालय प्रलेखन एक उपयोगी section इस का वर्णन शामिल हैं: के साथ Mock नीचे की तरह कुछ कोशिश

ऊपर ऐसा करने के लिए।

+0

यह मेरी समस्या के लिए हो जाता है। 'get_user_name'' test_method' की तुलना में एक अलग मॉड्यूल में है। क्या sub_module में कुछ मॉक करने का कोई तरीका है? मैंने इसे नीचे एक बदसूरत तरीके से तय किया। – nsfyn55

+4

इससे कोई फर्क नहीं पड़ता कि 'get_user_name'' test_method' से भिन्न मॉड्यूल में है क्योंकि आप 'app.mocking' में फ़ंक्शन आयात कर रहे हैं, वे एक ही नामस्थान में हैं। –

+0

मिला। हाँ, धन्यवाद काम करता है! – nsfyn55

5

जबकि मैटी जॉन का जवाब आपकी समस्या हल करता है (और मुझे भी मदद मिली, धन्यवाद!), हालांकि, मैं मजाक के साथ मूल 'get_user_name' फ़ंक्शन के प्रतिस्थापन को स्थानीयकृत करने का सुझाव दूंगा। जब फ़ंक्शन को प्रतिस्थापित किया जाता है और जब यह नहीं होता है तो यह आपको नियंत्रित करने की अनुमति देगा। इसके अलावा, यह आपको एक ही परीक्षण में कई प्रतिस्थापन करने की अनुमति देगा। ऐसा करने के लिए, एक बहुत simillar ढंग से '' का बयान का उपयोग करें:

from mock import patch 

class MockingTestTestCase(unittest.TestCase): 

    def test_mock_stubs(self): 
     with patch('app.mocking.get_user_name', return_value = 'Mocked This Silly'): 
      ret = test_method() 
      self.assertEqual(ret, 'Mocked This Silly') 
+0

को केवल स्टब करने की आवश्यकता है, यह इस तरह के प्रश्न के लिए असीमित है। चाहे आप सजावट के रूप में 'पैच' का उपयोग करें या संदर्भ प्रबंधक उपयोग मामले के लिए विशिष्ट है। मिसाल के तौर पर आप 'पैच' को 'xunit' या' pytest' क्लास में सभी परीक्षणों के लिए मूल्य बनाने के लिए एक सजावटी के रूप में उपयोग कर सकते हैं जबकि अन्य मामलों में संदर्भ प्रबंधक द्वारा प्रदान किए गए अच्छे दाग नियंत्रण के लिए उपयोगी होता है। – nsfyn55

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