एक आयातित मॉड्यूल से एक समारोह में पायथन मॉकिंग


125

मैं समझना चाहता हूं कि @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
सवाल "सर्वोत्तम प्रथाओं का मजाक उड़ाने" के बारे में है या नहीं या आप जो कर रहे हैं वह समझ में आता है या नहीं? पहले के बारे में मैं एक Mockमॉकिंग लाइब्रेरी का उपयोग करने के लिए कहूंगा , जैसे कि python3.3 + में शामिल है unittest.mock
बकुरीउ

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

जवाबों:


167

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

Mockनीचे की तरह कुछ करने की कोशिश के साथ ऊपर करने के लिए :

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')

मानक पुस्तकालय प्रलेखन में इसका वर्णन करने वाला एक उपयोगी खंड शामिल है ।


यह मेरी समस्या के लिए हो जाता है। get_user_nameसे भिन्न मॉड्यूल में है test_method। क्या सबमॉडल में किसी चीज का मजाक उड़ाने का कोई तरीका है? मैंने इसे नीचे एक बदसूरत तरीके से तय किया।
nsfyn55

6
इससे कोई फर्क नहीं पड़ता कि get_user_nameआप एक अलग मॉड्यूल में हैं test_methodक्योंकि आप फ़ंक्शन को app.mockingउसी नामस्थान में आयात कर रहे हैं।
मत्ती जॉन

2
Test_patch कहां से आया, यह वास्तव में क्या है?
माइक जी

2
test_patch पैच डेकोरेटर द्वारा पारित किया गया है और नकली get_user_name ऑब्जेक्ट (यानी मैजिकमॉक क्लास का एक उदाहरण) है। यह स्पष्ट हो सकता है अगर इसे कुछ नाम दिया गया था get_user_name_patch
मत्ती जॉन

आप test_method को कैसे संदर्भित कर रहे हैं? इसके परिणामस्वरूप त्रुटि होगी, NameError: वैश्विक नाम 'test_method' परिभाषित नहीं है
आदित्य

12

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

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')

6
यह समक्ष वाले प्रश्न के लिए सारहीन है। चाहे आप patchएक डेकोरेटर या संदर्भ प्रबंधक के रूप में उपयोग करें, उपयोग के मामले के लिए विशिष्ट है। उदाहरण के लिए, आप patchएक सज्जाकार के रूप में उपयोग कर सकते हैं एक xunitया pytestवर्ग में सभी परीक्षणों के लिए एक मूल्य नकली करने के लिए, जबकि अन्य मामलों में इसके उपयोगी संदर्भ प्रबंधक द्वारा नियंत्रित ठीक दानेदार नियंत्रण है।
nsfyn55
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.