1

In the below example , I have a decorator. In the decorator , I am instantiating a DB connection class. I have a test class below , where I want to mock the DB connection class within the decorator. How can I do that?

# 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) 
Punter Vicky
  • 15,954
  • 56
  • 188
  • 315
  • 1
    `db_conn = new DBConn()`. That looks like a syntax error. `DBConn()` is also not defined. How you instantiate the object is important to how it has to be mocked. – jordanm Apr 16 '20 at 19:42
  • @jordanm sorry , it was a typo. DBConn() is something that I added as an example here to see how it can be mocked. – Punter Vicky Apr 16 '20 at 19:53
  • Depends on how it's defined/imported – jordanm Apr 16 '20 at 20:09
  • @jordanm the function works as expected. However instead of DConn creating an actual class , I would like to create a mock class. In general I use decorator patch(packagename.DBConn) to patch it. However since it is a decorator , I am not sure how to combine the patch decorator with calculate_time decorator – Punter Vicky Apr 16 '20 at 20:32
  • Should be mocked just as imported, e.g. `@patch('.DBConn')`, provided it is imported like `from xxx import DBConn`. Nothing special here because of the decorator. It would help if you would add how you import `DBConn` to your question. – MrBean Bremen Apr 17 '20 at 18:23

1 Answers1

0

Ok, to make this clearer:
Provided your modules live in the package mypackage, and your module calculate_time.py with the decorator looks like:

from mypackage.dbconn import DBConn

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

And you have the module factorial.py with:

from mypackage.calculate_time import calculate_time

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

Then your test could look like this:

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))
MrBean Bremen
  • 14,916
  • 3
  • 26
  • 46