i'm quite new to python and mocking generally. So I tried to find a solution to my problem, through reading the documentation: https://docs.python.org/3/library/unittest.mock.html#magic-methods, following article: http://alexmarandon.com/articles/python_mock_gotchas/ and lots of stackoverflow-questions. But I couldn't find a solution yet.
I try to mock two function, which are creating a database connection and put the data into a pandas dataFrame. They are used in the post-function (overwrites the django post-function):
def post(self, request, *args, **kwargs):
db_connection = du_db.get_connection(dbtype='mssql', username=crd.MS_SQL_USER, password=crd.MS_SQL_PWD)
df = du_db.fetch_dataframe(sql, connection=db_connection)
In the testing environment, get_connection should return nothing and fetch_dataframe should return a pandas dataframe defined before.
My testing class looks like this:
class IndexViewTest(TestCase):
@mock.patch('du_db.db.get_connection')
@mock.patch('du_db.db.fetch_dataframe')
def setUp(self, mock_get_connection, mock_fetch_dataframe):
self.c = Client()
mock_get_connection = mock_get_connection()
mock_fetch_dataframe = mock_fetch_dataframe()
mock_get_connection.return_value = ""
df = {'lot_of_data': ['xy', 'z'], 'more_data': [8, 9]}
mock_fetch_dataframe.return_value = pd.DataFrame(df)
assert mock_get_connection is data_utils.db.get_connection()
assert mock_fetch_dataframe is data_utils.db.fetch_dataframe()
assert mock_get_connection.called
assert mock_get_connection.called
# Lot of test-functions similar to this:
def test_valid_data(self):
resp = self.c.post('/', data={'id': 3338})
self.assertEqual(resp.status_code, 200)
self.assertContains(resp, 'Hello', status_code=200)
I get the following error-message:

The replacing of the original functions through the mocks doesn't seam to work.
Thanks for your help.
class IndexViewTest(TestCase):
@mock.patch('du_db.db.get_connection')
@mock.patch('du_db.db.fetch_dataframe')
def setUp(self, mock_fetch_dataframe, mock_get_connection):
self.c = Client()
mock_get_connection = mock_get_connection() # remove this
mock_fetch_dataframe = mock_fetch_dataframe() # remove this
When you call the mocks above, they return another new mock. By assigning to the same name, you are loosing the references to the patched mocks. You will be unable to configure or inspect them.
mock_get_connection.return_value = "" # this is NOT the mock you think
# unless removing lines above.
# And so on...
df = {'lot_of_data': ['xy', 'z'], 'more_data': [8, 9]}
mock_fetch_dataframe.return_value = pd.DataFrame(df)
# data__utils or du_db ??
assert mock_get_connection is data_utils.db.get_connection()
assert mock_fetch_dataframe is data_utils.db.fetch_dataframe()
assert mock_get_connection.called
assert mock_get_connection.called
# Lot of test-functions similar to this:
def test_valid_data(self):
resp = self.c.post('/', data={'id': 3338})
self.assertEqual(resp.status_code, 200)
self.assertContains(resp, 'Hello', status_code=200)
Edit: From what I understand, you already see the mocks at work from pdb. To make the tests work as you like, you need to patch every test function that uses those two functions for example with patch decorators. Then you have to setup the mocks inside the patched test functions. Also usually you assert in the tests but not in the setUp. I understand you made it here just for convenience as you were with some doubts about the running code.
If you were thinking in setting up the mocks in setUp for other test functions to use (you can't do it just like that, you would have to store them in self and then manage them again in the test functions), maybe you are interested in this example from Mock documentation:
An alternative way of managing patches is to use the patch methods: start and stop. These allow you to move the patching into your setUp and tearDown methods.
>>> class MyTest(TestCase):
...
def setUp(self):
...
self.patcher = patch(’mymodule.foo’)
...
self.mock_foo = self.patcher.start()
...
...
def test_foo(self):
...
self.assertTrue(mymodule.foo is self.mock_foo)
...
...
def tearDown(self):
...
self.patcher.stop()
...
>>> MyTest(’test_foo’).run()
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