【问题标题】:Test decorator parameters测试装饰器参数
【发布时间】:2019-02-21 16:44:18
【问题描述】:

我有一个装饰器,它接受两个参数 callbackonerror,两者都应该是这样的可调用对象

class mydecorator(object):
    def __init__(self, callback, onerror=None):
        if callable(callback):
            self.callback = callback
        else:
            raise TypeError('Callable expected in "callback" parameter')

        self.onerror = onerror
        if self.onerror and not callable(self.onerror):
            raise TypeError('Callable expected in "onerror" parameter')

    def __call__(self, func):
        return self.__param__call__(func)

    def __param__call__(self, func):
        def wrapper(*args, **kwargs):
            result = func(*args, **kwargs)
            try:
                self.callback()
            except MyCustomException as e:
                if self.onerror:
                    self.onerror(e.message, e.data)
                else:
                    raise

            return result 
        return wrapper

我想测试我传递了一个无效参数,例如一个不可调用的,它应该引发一个TypeError

使用 Python unittest 实现此目的的最佳方法是什么?我愿意做这样的事情:

def test_non_callable_callback_should_return_type_error(self):
    try:
        @mydecorator('this_is_not_a_callable')
        def my_phony_func():
            pass
    except TypeError:
        # Correctly has raised a TypeError, lets just pass
        pass
    else:
        # It has not raised an TypeError, let's fail
        self.fail('TypeError not raised when a non callable passed to callback')

这一定是一个更好的方法,不是吗?

【问题讨论】:

  • 必须有更好的方法来做什么?如果不寻常,您使用带有可调用实例的类是非常好的(我更习惯于看到常规函数被用作装饰器)。测试也OK。如果您使用 py.test,它有一个方便的with pytest.raises(SystemExit): ...code...,可以让此类测试更加紧凑。

标签: python unit-testing python-decorators


【解决方案1】:

正如Leo K 评论的那样,有一种更简单的方法可以测试某些代码是否在测试中引发异常,尽管不同的库拼写略有不同。在unittest.TestCase 中,您可以使用self.assertRaises 作为上下文管理器:

def test_non_callable_callback_should_return_type_error(self):
    with self.assertRaises(TypeError):
        @mydecorator('this_is_not_a_callable')
        def my_phony_func():
            pass

事实上,您可以通过删除被测试代码中不必要的部分来进一步简化事情。由于您希望 mydecorator 类在被调用时引发异常(而不是在函数上调用实例时),因此您可以摆脱虚拟函数并一起跳过 @decorator 语法。 assertRaises 方法甚至可以为您拨打电话:

def test_non_callable_callback_should_return_type_error(self):
    self.assertraises(TypeError, mydecorator, 'this_is_not_a_callable')

【讨论】:

    猜你喜欢
    • 2011-02-13
    • 2017-08-20
    • 2015-10-16
    • 1970-01-01
    • 2011-12-20
    • 2021-01-20
    • 1970-01-01
    • 2012-11-01
    • 2019-07-29
    相关资源
    最近更新 更多