What is mocking in Python? Mocking in Python means the unittest. mock library is being utilized to replace parts of the system with mock objects, allowing easier and more efficient unit testing than would otherwise be possible.
In pytest , mocking can replace the return value of a function within a function. This is useful for testing the desired function and replacing the return value of a nested function within that desired function we are testing.
patch() unittest. mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock . Usually, you use patch() as a decorator or a context manager to provide a scope in which you will mock the target object.
Instead of mocking, you could simply subclass the database class and test against that:
class TestingDatabaseThing(DatabaseThing):
def __init__(self, connection):
self.connection = connection
and instantiate that class instead of DatabaseThing
for your tests. The methods are still the same, the behaviour will still be the same, but now all methods using self.connection
use your test-supplied connection instead.
You should use mock
package to mock the method __init__
of the class:
from mock import patch
def test_database_thing(self):
def __init__(self, dbName, user, password):
# do something else
with patch.object(DatabaseThing, '__init__', __init__):
# assert something
Please refer to @Martijn Pieters' answer.
A long term solution is to have the client create the connection and hand it over to DatabaseThing
to use. Using the Single Responsibility principle, I don't think DatabaseThing
should be responsible for making the connection in this case.
This technique cuts dependencies and gives you a lot more flexibility e.g. you can setup a connection pool and give each new instance of DatabaseThing
a connection from the pool, without changing anything in DatabaseThing
.
Rather than try to replace the init function which is messy, fragile and hacky, try passing a function to your database constructor as shown below:
# Test connection creation
def connect_lite(dbName=None, user=None, password=None):
connection = lite.connect(":memory:")
cur = self.connection.cursor()
cur.executescript ('''CREATE TABLE APPLE (VERSION INT, AMNT SMALLINT);
INSERT INTO APPLE VALUES(16,0);
INSERT INTO APPLE VALUES(17,5);
INSERT INTO APPLE VALUES(18,1);
INSERT INTO APPLE VALUES(19,15);
INSERT INTO APPLE VALUES(20,20);
INSERT INTO APPLE VALUES(21,25);''')
return cur
# Production connection creation
def connect_ibm(dbName, user, password):
return ibm_db_dbi.connect(dbName, user, password)
# Your DatabaseThing becomes:
class DatabaseThing():
def __init__(self, connect, dbName, user, password):
self.connection = connect(dbName, user, password)
# In your test create a DatabaseThing
t = DatabaseThing(connect_lite, dbName, user, password)
# In your production code create a DatabaseThing
p = DatabaseThing(connect_ibm, dbName, user, password)
This has the side benefit of slightly decoupling your code from the database technology you are using.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With