模拟函数以引发异常以测试 except 块

Mocking a function to raise an Exception to test an except block(模拟函数以引发异常以测试 except 块)
本文介绍了模拟函数以引发异常以测试 except 块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

我有一个函数 (foo),它调用另一个函数 (bar).如果调用bar()引发了HttpError,如果状态码是404我想特别处理,否则重新引发.

I have a function (foo) which calls another function (bar). If invoking bar() raises an HttpError, I want to handle it specially if the status code is 404, otherwise re-raise.

我正在尝试围绕这个 foo 函数编写一些单元测试,模拟对 bar() 的调用.不幸的是,我无法获得对 bar() 的模拟调用来引发我的 except 块捕获的异常.

I am trying to write some unit tests around this foo function, mocking out the call to bar(). Unfortunately, I am unable to get the mocked call to bar() to raise an Exception which is caught by my except block.

这是说明我的问题的代码:

Here is my code which illustrates my problem:

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

我按照 Mock docs 说您应该将 Mock 实例的 side_effect 设置为 Exception 类,以使模拟函数引发错误.

I followed the Mock docs which say that you should set the side_effect of a Mock instance to an Exception class to have the mocked function raise the error.

我还查看了一些其他相关的 StackOverflow Q&As,看起来我正在做与他们正在做的事情相同的事情,以导致他们的模拟引发异常.

I also looked at some other related StackOverflow Q&As, and it looks like I am doing the same thing they are doing to cause and Exception to be raised by their mock.

  • https://stackoverflow.com/a/10310532/346561
  • 如何使用 Python Mock 引发异常 - 但将 Errno 设置为给定值

为什么设置 barMockside_effect 不会引发预期的 Exception?如果我在做一些奇怪的事情,我应该如何在我的 except 块中测试逻辑?

Why is setting the side_effect of barMock not causing the expected Exception to be raised? If I am doing something weird, how should I go about testing logic in my except block?

推荐答案

你的 mock 可以很好地引发异常,但是缺少 error.resp.status 值.与其使用 return_value,不如告诉 Mock status 是一个属性:

Your mock is raising the exception just fine, but the error.resp.status value is missing. Rather than use return_value, just tell Mock that status is an attribute:

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

Mock() 的附加关键字参数被设置为结果对象的属性.

Additional keyword arguments to Mock() are set as attributes on the resulting object.

我将您的 foobar 定义放在 my_tests 模块中,并添加到 HttpError class 所以我可以使用它也一样,然后你的测试就可以成功了:

I put your foo and bar definitions in a my_tests module, added in the HttpError class so I could use it too, and your test then can be ran to success:

>>> 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() 从第二个参数设置的属性.

You can even see the print '404 - %s' % error.message line run, but I think you wanted to use error.content there instead; that's the attribute HttpError() sets from the second argument, at any rate.

这篇关于模拟函数以引发异常以测试 except 块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

本站部分内容来源互联网,如果有图片或者内容侵犯您的权益请联系我们删除!

相关文档推荐

patching a class yields quot;AttributeError: Mock object has no attributequot; when accessing instance attributes(修补类会产生“AttributeError:Mock object has no attribute;访问实例属性时)
How to mock lt;ModelClassgt;.query.filter_by() in Flask-SqlAlchemy(如何在 Flask-SqlAlchemy 中模拟 lt;ModelClassgt;.query.filter_by())
FTPLIB error socket.gaierror: [Errno 8] nodename nor servname provided, or not known(FTPLIB 错误 socket.gaierror: [Errno 8] nodename nor servname provided, or not known)
Weird numpy.sum behavior when adding zeros(添加零时奇怪的 numpy.sum 行为)
Why does the #39;int#39; object is not callable error occur when using the sum() function?(为什么在使用 sum() 函数时会出现 int object is not callable 错误?)
How to sum in pandas by unique index in several columns?(如何通过几列中的唯一索引对 pandas 求和?)