测试装饰器参数

问题描述 投票:1回答:1

我有一个装饰器接受两个参数callbackonerror,两者都应该是这样的callables

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

它一定是更好的方式,不是吗?

python unit-testing python-decorators
1个回答
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')
© www.soinside.com 2019 - 2024. All rights reserved.