关于python:绕过装饰器进行单元测试

Bypassing a decorator for unit testing

本问题已经有最佳答案,请猛点这里访问。

我有一个装饰器@auth,它基本上检查数据库,以确保用户可以访问给定的REST调用。 我想为这些调用编写一些单元测试。 我最初的想法是简单地将装饰器单独打包成一个无效的通道。 (我最初的想法失败了,所以我可能只是将@auth内的一些函数monkeypatch以便它总是通过,但我仍然很好奇我是否可以完全绕过装饰器)

我汇总了一份我希望完成的快速样本。

example.py

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# example.py
from __future__ import print_function

def sample_decorator(func):
    def decorated(*args, **kwargs):
        print("Start Calculation")
        ans = func(*args, **kwargs) + 3
        print(ans)
        print("Finished")
        return ans
    return decorated

@sample_decorator
def add(a, b):
    return a + b

test_example.py

1
2
3
4
5
6
7
8
9
10
11
12
# test_example.py
from __future__ import print_function
import pytest

import example

def test_add_with_decorator():
    assert example.add(1, 1) == 5

def testadd_with_monkeypatch_out_decorator(monkeypatch):
    monkeypatch.setattr(example, 'sample_decorator', lambda func: func)
    assert example.add(1, 1) == 2  # this fails, but is the behaviour I want

是否有一些直接的方法来实现这一目标?


装饰器可以在包装函数上设置一个属性,以便访问包装函数。

沿途的东西

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
def wrap_foo(func):
 def decorated(*args, **kwargs):
  func(*args, **kwargs)
 decorated.__wrapped_fn = func
 return decorated

@wrap_foo
def foo():
 pass

# Wrapped
foo()

# Unwrapped
foo.__wrapped_fn()


只需将定义分开:

1
2
3
4
5
def raw_add...

add = sample_decorator(raw_add)

assert example.raw_add...