एक फ़ंक्शन / विधि को मुखर का उपयोग करके बुलाया नहीं गया था


131

मैं अपने आवेदन का परीक्षण करने के लिए मॉक लाइब्रेरी का उपयोग कर रहा हूं, लेकिन मैं यह दावा करना चाहता हूं कि कुछ फ़ंक्शन को नहीं बुलाया गया था। मॉक डॉक्स जैसे तरीकों के बारे में बात करते हैं mock.assert_called_withऔर mock.assert_called_once_with, लेकिन मुझे कुछ भी ऐसा नहीं मिला जैसा mock.assert_not_calledकि सत्यापित मॉक से संबंधित कुछ भी नहीं कहा गया था ।

मैं निम्नलिखित की तरह कुछ के साथ जा सकता है, हालांकि यह शांत नहीं लगता है और न ही पायथोनिक:

def test_something:
    # some actions
    with patch('something') as my_var:
        try:
            # args are not important. func should never be called in this test
            my_var.assert_called_with(some, args)
        except AssertionError:
            pass  # this error being raised means it's ok
    # other stuff

किसी भी विचार यह कैसे पूरा करने के लिए?


जैसा कि उनके उत्तर में @Ahmet बताते हैं, assert_not_called अब समर्थित है, बैकपोर्ट ( docs.python.org/3/library/… ) में भी।
मार्टिन

जवाबों:


144

यह आपके मामले के लिए काम करना चाहिए;

assert not my_var.called, 'method should not have been called'

नमूना;

>>> mock=Mock()
>>> mock.a()
<Mock name='mock.a()' id='4349129872'>
>>> assert not mock.b.called, 'b was called and should not have been'
>>> assert not mock.a.called, 'a was called and should not have been'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AssertionError: a was called and should not have been

क्या इस जवाब के लिए Django की आवश्यकता है? मुझे एक त्रुटि मिल रही है:AttributeError: MockCallable instance has no attribute 'called'
नाथन आर्थर

@ नथनअर्थर एचएम, मुझे ऐसा नहीं लगता, मैकओएस के बाद sudo easy_install -U mockऔर from mock import Mockऊपर, बिना हिचके चलता है। कभी भी Django :) को स्थापित नहीं किया गया
जोकिम इस्कसन

हम्म। अजीब है कि। मैं पायथन 2.7.1 चला रहा हूं और from mock import Mockअपने परीक्षणों के लिए सबसे बेकार और पायथन मॉक 0.1.0 का उपयोग कर रहा हूं । क्या उस ध्वनि की कोई समस्या है?
नाथन आर्थर

मैं किसी अन्य मॉड्यूल से एक module_to_test.another_module.class = mock.Mock()कॉल करने योग्य वर्ग का मजाक उड़ा रहा हूं, इसलिए ऐसा लगता है , क्या आप इसकी पुष्टि कर सकते हैं कि विभिन्न परीक्षण मामलों (unittest.TestCase उदाहरणों) पर कॉल याद नहीं है? मुझे लगता है कि इस मामले में कॉल काउंट रीसेट नहीं होता है
0xc0de

66

हालांकि एक पुराना सवाल है, मैं यह कहना चाहूंगा कि वर्तमान में mockपुस्तकालय (unittest.mock का बैकपोर्ट) assert_not_calledविधि का समर्थन करता है।

बस अपग्रेड करो तुम्हारा;

pip install mock --upgrade


29

आप calledविशेषता की जांच कर सकते हैं , लेकिन यदि आपका दावा विफल हो जाता है, तो अगली चीज़ जो आप जानना चाहते हैं , वह अप्रत्याशित कॉल के बारे में कुछ है , इसलिए आप शुरू से प्रदर्शित करने के लिए उस जानकारी को व्यवस्थित कर सकते हैं। का उपयोग कर unittest, आप call_args_listइसके बजाय की सामग्री की जाँच कर सकते हैं :

self.assertItemsEqual(my_var.call_args_list, [])

जब यह विफल होता है, तो यह इस तरह एक संदेश देता है:

अभिकथन: तत्व गणना समान नहीं थी:
पहले में 0 है, दूसरे में 1: कॉल है ('पहला तर्क', 4)

14

जब आप कक्षा का उपयोग कर परीक्षण करते हैं तो आप एकसाथ विरासत में प्राप्त कर सकते हैं। ऐसा करने के लिए आप निम्न विधियों का उपयोग कर सकते हैं:

  • assertTrue
  • assertFalse
  • assertEqual

और इसी तरह ( अजगर प्रलेखन में आप बाकी को ढूंढते हैं)।

आपके उदाहरण में हम केवल यह दावा कर सकते हैं कि mock_method.call की गई संपत्ति गलत है , जिसका अर्थ है कि विधि को नहीं बुलाया गया था।

import unittest
from unittest import mock

import my_module

class A(unittest.TestCase):
    def setUp(self):
        self.message = "Method should not be called. Called {times} times!"

    @mock.patch("my_module.method_to_mock")
    def test(self, mock_method):
        my_module.method_to_mock()

        self.assertFalse(mock_method.called,
                         self.message.format(times=mock_method.call_count))

11

python >= 3.5आप के साथ उपयोग कर सकते हैं mock_object.assert_not_called()


1

अन्य जवाबों को देखते हुए, @ लूट-केनेडी को छोड़कर किसी ने भी इस बारे में बात नहीं की call_args_list

यह एक शक्तिशाली उपकरण है जिसके लिए आप इसके ठीक विपरीत लागू कर सकते हैं MagicMock.assert_called_with()

call_args_listcallवस्तुओं की एक सूची है । प्रत्येक callऑब्जेक्ट एक नकली कॉल करने योग्य कॉल का प्रतिनिधित्व करता है।

>>> from unittest.mock import MagicMock
>>> m = MagicMock()
>>> m.call_args_list
[]
>>> m(42)
<MagicMock name='mock()' id='139675158423872'>
>>> m.call_args_list
[call(42)]
>>> m(42, 30)
<MagicMock name='mock()' id='139675158423872'>
>>> m.call_args_list
[call(42), call(42, 30)]

किसी callवस्तु का उपभोग करना आसान है, क्योंकि आप इसकी तुलना लंबाई 2 के एक टपल के साथ कर सकते हैं जहां पहला घटक एक टपल है जिसमें संबंधित कॉल के सभी स्थिति संबंधी तर्क हैं, जबकि दूसरा घटक कीवर्ड तर्कों का एक शब्दकोश है।

>>> ((42,),) in m.call_args_list
True
>>> m(42, foo='bar')
<MagicMock name='mock()' id='139675158423872'>
>>> ((42,), {'foo': 'bar'}) in m.call_args_list
True
>>> m(foo='bar')
<MagicMock name='mock()' id='139675158423872'>
>>> ((), {'foo': 'bar'}) in m.call_args_list
True

तो, ओपी की विशिष्ट समस्या का समाधान करने का एक तरीका है

def test_something():
    with patch('something') as my_var:
        assert ((some, args),) not in my_var.call_args_list

ध्यान दें कि इस तरह, केवल जाँच करने के बजाय अगर एक मॉक कॉल करने योग्य कॉल किया गया है, के माध्यम से MagicMock.called, आप अब यह जांच सकते हैं कि क्या इसे एक विशिष्ट तर्क के साथ बुलाया गया है।

यह उपयोगी है। मान लें कि आप किसी ऐसे फ़ंक्शन का परीक्षण करना चाहते हैं, जो किसी सूची को लेता है और किसी अन्य फ़ंक्शन को कॉल करता है, सूची compute()के प्रत्येक मूल्य के लिए केवल तभी जब वे किसी विशिष्ट स्थिति को संतुष्ट करते हैं।

अब आप मॉक कर सकते हैं compute, और परीक्षण कर सकते हैं कि क्या इसे कुछ मूल्य पर बुलाया गया है, लेकिन दूसरों पर नहीं।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.