एक अपवाद को रोकने के लिए एक अपवाद को बढ़ाने के लिए एक फ़ंक्शन का मजाक उड़ाया


119

मेरे पास एक फ़ंक्शन ( foo) है जो दूसरे फ़ंक्शन को कॉल करता है ( bar)। अगर आह्वान bar()उठता है HttpError, तो मैं इसे विशेष रूप से संभालना चाहता हूं यदि स्थिति कोड 404 है, अन्यथा फिर से बढ़ाएं।

मैं इस fooफंक्शन के आसपास कुछ यूनिट टेस्ट लिखने की कोशिश कर रहा हूं , जिसमें कॉल का मजाक उड़ाया गया है bar()। दुर्भाग्य से, मैं bar()एक अपवाद को उठाने के लिए नकली कॉल प्राप्त करने में असमर्थ हूं जो मेरे exceptब्लॉक द्वारा पकड़ा गया है ।

यहाँ मेरा कोड है जो मेरी समस्या को दर्शाता है:

import unittest
import mock
from apiclient.errors import HttpError


class FooTests(unittest.TestCase):
    @mock.patch('my_tests.bar')
    def test_foo_shouldReturnResultOfBar_whenBarSucceeds(self, barMock):
        barMock.return_value = True
        result = foo()
        self.assertTrue(result)  # passes

    @mock.patch('my_tests.bar')
    def test_foo_shouldReturnNone_whenBarRaiseHttpError404(self, barMock):
        barMock.side_effect = HttpError(mock.Mock(return_value={'status': 404}), 'not found')
        result = foo()
        self.assertIsNone(result)  # fails, test raises HttpError

    @mock.patch('my_tests.bar')
    def test_foo_shouldRaiseHttpError_whenBarRaiseHttpErrorNot404(self, barMock):
        barMock.side_effect = HttpError(mock.Mock(return_value={'status': 500}), 'error')
        with self.assertRaises(HttpError):  # passes
            foo()

def foo():
    try:
        result = bar()
        return result
    except HttpError as error:
        if error.resp.status == 404:
            print '404 - %s' % error.message
            return None
        raise

def bar():
    raise NotImplementedError()

मैं पीछा किया मॉक डॉक्स जो कहते हैं कि तुम स्थापित करना चाहिए side_effectएक के Mockएक करने के लिए उदाहरण Exceptionमज़ाक उड़ाया समारोह बढ़ाने त्रुटि के लिए वर्ग।

मैंने कुछ अन्य संबंधित StackOverflow Q & As को भी देखा, और ऐसा लग रहा है कि मैं वही काम कर रहा हूं जो वे कर रहे हैं और अपवाद उनके मजाक द्वारा उठाया जा रहा है।

क्यों स्थापित कर रही है side_effectकी barMockउम्मीद के कारण नहीं Exceptionउठाया जा? अगर मैं कुछ अजीब कर रहा हूं, तो मुझे अपने exceptब्लॉक में तर्क परीक्षण के बारे में कैसे जाना चाहिए ?


मैं बहुत यकीन है कि अपने अपवाद हूँ है उठाया जा रहा है, लेकिन मुझे यकीन है कि कैसे आप सेट कर रहे हैं नहीं कर रहा हूँ resp.statusकोड वहाँ। कहाँ HTTPErrorसे आता है?
मार्टिन पीटर्स

@MartijnPieters Google के libHttpError में परिभाषित एक वर्ग है जिसका उपयोग हम GAE में करते हैं। इसे परिमों के साथ परिभाषित किया गया है, इसलिए मैं प्रतिक्रिया के लिए एक नकली उदाहरण बनाने का प्रयास कर रहा था, जिसमें उपयुक्त स्थिति कोड निर्दिष्ट था। apiclient__init__(resp, content)
जेसी वेब

सही है, तो यह इस वर्ग है ; लेकिन आपको return_valueतब उपयोगकर्ता की आवश्यकता नहीं है ; respनहीं बुलाया जा रहा है
मार्टिन पीटर्स

1
मैंने अपने कोड का उपयोग किए बिना फिर से HttpErrorकोशिश की और इसके बजाय सिर्फ एक नियमित Exceptionउदाहरण का उपयोग करने की कोशिश की । यह पूरी तरह से काम करता है। इसका मतलब यह है कि यह कुछ करना होगा कि मैं कैसे HttpErrorउदाहरण को कॉन्फ़िगर कर रहा हूं , संभवत: संबंधित है कि मैं कैसे Mockप्रतिक्रिया के लिए एक उदाहरण बना रहा हूं ।
जेसी वेब

जवाबों:


141

आपका मजाक केवल ठीक-ठीक अपवाद को बढ़ा रहा है, लेकिन error.resp.statusमूल्य गायब है। उपयोग करने के बजाय return_value, बस यह बताएं Mockकि statusएक विशेषता है:

barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')

अतिरिक्त कीवर्ड तर्क Mock()परिणामी वस्तु पर विशेषता के रूप में सेट किए जाते हैं।

मैंने आपकी fooऔर barपरिभाषाओं को एक my_testsमॉड्यूल में रखा , HttpErrorकक्षा में जोड़ा ताकि मैं भी इसका उपयोग कर सकूं, और आपका परीक्षण फिर सफलता के लिए भाग सकता है:

>>> from my_tests import foo, HttpError
>>> import mock
>>> with mock.patch('my_tests.bar') as barMock:
...     barMock.side_effect = HttpError(mock.Mock(status=404), 'not found')
...     result = my_test.foo()
... 
404 - 
>>> result is None
True

तुम भी print '404 - %s' % error.messageलाइन रन देख सकते हैं , लेकिन मुझे लगता है कि आप error.contentइसके बजाय उपयोग करना चाहते थे ; यह विशेषता HttpError()किसी भी दर पर दूसरे तर्क से सेट होती है।


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