简体   繁体   中英

Hot to pytest that a decorator is assigned to multiple functions

I read somewhere on SO that you should not test the decorator but the functionality of the wrapped function. Nevertheless there might be a shorter way of testing whether a certain decorator is assigned to multiple functions.

I have this decorator:

def check_user(func):
    """Only allow admins to change the user_id in the annotated function.

    Use as decorator: @check_user
    """

    @wraps(func)
    def wrapper(*args, **kwargs):
    ...

I have some tests to test the decorator function itself, eg:

def test_check_user(self):
    """Test the check user decorator if a non admin wants to overwrite the user."""
    with pytest.raises(ValueError) as ex:

        @check_user
        def foo(login: str, userId: str):
            return True

        foo(login="Foo", userId="Bar")

    assert ex.value.args[0] == "Only admin users may overwrite the userId."

Now I have about 20 FastAPI endpoints where I assigned this decorator. I want to avoid to repeat the same tests (see example above and other tests) for each function. So something like this would be great:

@pytest.mark.parametrize("method", ["foo", "bar", "gaga", ....])
def test_decorated_methods(self, method):
    assert assigned(check_user, method)  # or so

You should be able to modify and parametrize test_check_user to check the same assert for every decorated function in one test. This is superior to just checking if a decorator is applied because, it validates the actual functional requirement of preventing non-admins from changing userId. Remember the goal of writing good tests is to protect you from your future self. While you currently feel you can infer a security feature from the presence of this decorator, can you be sure that this inference will always be true for the rest of the project's lifetime? Better to make sure that your security features actually behave as intended.

@pytest.mark.parametrize("method,args,kwargs", [("myfunc", ["Foo"], {})])
def test_cant_change_id_if_not_admin(func, args, kwargs):
    kwargs["userId"]="Bar"
    with pytest.raises(ValueError) as ex:
        func(*args, **kwargs)
    assert ex.value.args[0] == "Only admin users may overwrite the userId."

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM