【问题标题】:mocking objects within a decorator while using pytest在使用 pytest 时在装饰器中模拟对象
【发布时间】:2020-07-30 04:27:07
【问题描述】:

在下面的例子中,我有一个装饰器。在装饰器中,我正在实例化一个数据库连接类。我在下面有一个测试类,我想在装饰器中模拟数据库连接类。我该怎么做?

# importing libraries 
import time 
import math 

# decorator to calculate duration 
# taken by any function. 
def calculate_time(func): 

    # added arguments inside the inner1, 
    # if function takes any arguments, 
    # can be added like this. 
    def inner1(*args, **kwargs): 

        db_conn = DBConn()
        # storing time before function execution 
        begin = time.time() 

        func(*args, **kwargs) 

        # storing time after function execution 
        end = time.time() 
        db_conn.logTime(begin, end)
        print("Total time taken in : ", func.__name__, end - begin) 

    return inner1 



# this can be added to any function present, 
# in this case to calculate a factorial 
@calculate_time
def test_factorial(num): 

    # sleep 2 seconds because it takes very less time 
    # so that you can see the actual difference 
    time.sleep(2) 
    print(math.factorial(num)) 

# calling the function. 
factorial(10) 

【问题讨论】:

  • db_conn = new DBConn()。这看起来像一个语法错误。 DBConn() 也没有定义。如何实例化对象对于如何模拟它很重要。
  • @jordanm 抱歉,这是一个错字。 DBConn() 是我在此处添加的示例,以了解如何模拟它。
  • 取决于它的定义/导入方式
  • @jordanm 该功能按预期工作。但是,我想创建一个模拟类,而不是 DConn 创建一个实际的类。一般来说,我使用装饰器补丁(packagename.DBConn)来修补它。但是由于它是一个装饰器,我不确定如何将补丁装饰器与 calculate_time 装饰器结合起来
  • 应该像导入一样被模拟,例如@patch('<module_with_calculate_time>.DBConn'),前提是它像 from xxx import DBConn 一样导入。由于装饰师,这里没有什么特别的。如果您将如何导入 DBConn 添加到您的问题中会有所帮助。

标签: python python-3.x pytest python-unittest python-decorators


【解决方案1】:

好的,为了更清楚:
假设您的模块位于包 mypackage 中,并且带有装饰器的模块 calculate_time.py 看起来像:

from mypackage.dbconn import DBConn

def calculate_time(func):
    def inner1(*args, **kwargs):
        ...

你有 factorial.py 的模块:

from mypackage.calculate_time import calculate_time

@calculate_time
def factorial(num):
    time.sleep(2)
    print(math.factorial(num))

那么您的测试可能如下所示:

from unittest.mock import patch    
from mypackage.factorial import factorial

class FakeConn:
    def logTime(self, begin, end):
        print(begin, end)

@patch('mypackage.calculate_time.DBConn', new=FakeConn)
def test_factorial():
    print(factorial(10))

【讨论】:

    猜你喜欢
    • 2016-08-17
    • 2020-09-20
    • 2022-11-11
    • 2018-12-30
    • 2019-02-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多