Robinson Wei
Robinson Wei

Reputation: 163

mock patch function

I am a newbie in python mock, recently I am trying to write a test code for my function. The function is used to analyze a Mongo database and from a CSV report. And I want to patch the "get_collection()" function. The structure is like this:

mongo_report.py file:

import pymongo

def get_collection(): # used to get mongo collection

def from_report():  #used to from a report
    get_collection(mongodb, mongo_collection_name)
    .....

In my test file:

from mongo_report import from_report
from mock import Mock, patch

def mock_get_collection():  # used to replace get_collection() 
    mocked_collection = Mock()
    mock_get_collection.count.side_effect = [20, 6, 2]
    mock_get_collection.find.side_effect = [{user: xx}]
    return mocked_collection

@patch('mongo_report.get_collection')
def mongo_report_test(mock_call):
    mock_call.return_value = mock_get_collection()
    from_report()

The patch is written by what I learned on a webpage https://blog.fugue.co/2016-02-11-python-mocking-101.html
but it didn't work.So my question is:

  1. Is this the right way to use patch, if not, how can I patch it?

  2. At mongo_report_test(mock_call), where is the mock_call come from, it doesn't linked to anything here, how can I declare it

  3. After patch, how can I call this test function?

Start learning from decorator, spend a whole day bumping my head to the desk, but still didn't learn the trick. :<

Upvotes: 1

Views: 2201

Answers (2)

Gang
Gang

Reputation: 2768

It took me a while to figure out that the original answer is misleading. Here is a working copy of mock very similar to your question, the only thing I did not know is your return value of get_connection(). python v2.6.6

    #/usr/bin/env pthon
    import unittest
    import mock
    from mock import MagicMock

    class Mongo(object):
        def __init__(self, *args, **kwargs):
            # doing nothing for demo
            pass

        def get_collection(self, input1):
            # return fixed list for demo
            return [1, 3, 5]

        def from_report(self, input_a, input_b):
            collection_a = self.get_collection(input_a)
            collection_b = self.get_collection(input_b)
            return collection_a + collection_b

    class TestMongo(unittest.TestCase):

        def setUp(self):
            self.expected = [2, 4, 6, 2, 4, 6]
            self.mock_value = [2, 4, 6]

        def tearDown(self):
            pass

        """ in the format of file_name.class_name.method_name
        @mock.patch('test_mongo.Mongo.get_collection')
        def test_using_mock_patch(self, mock_get_collection):
            mock_get_collection.return_value = self.mock_value
            mongo = Mongo()
            mongo.get_collection = mock_get_collection
            result = mongo.from_report('any', 'where')
            self.assertEquals(result, self.expected)

        """ mock.MagicMock
        def test_mongo_get_collection_using_magicMock(self):
            mock_mongo = MagicMock(name='get_collection')
            mock_mongo.get_collection.return_value = self.mock_value
            mongo = Mongo()
            mongo.get_collection = mock_mongo.get_collection
            result = mongo.from_report('any', 'where')
            self.assertEquals(result, self.expected)

        """ mock.Mock
        def test_mongo_get_collection_using_Mock(self):
            mock_mongo = mock.Mock(name='get_collection')
            mock_mongo.get_collection.return_value = self.mock_value
            mongo = Mongo()
            mongo.get_collection = mock_mongo.get_collection
            result = mongo.from_report('any', 'where')
            self.assertEquals(result, self.expected)


    if __name__ == '__main__':
        suite = unittest.TestLoader().loadTestsFromTestCase(TestMongo)
        unittest.TextTestRunner(verbosity=2).run(suite)

Here is the commands and output

    -bash-4.1$ python test_mongo.py
    test_mongo_get_collection_using_Mock (__main__.TestMongo) ... ok
    test_mongo_get_collection_using_magicMock (__main__.TestMongo) ... ok
    test_using_mock_patch (__main__.TestMongo) ... ok

    ----------------------------------------------------------------------
    Ran 3 tests in 0.005s

    OK
    -bash-4.1$ nosetests -vv test_mongo.py

Upvotes: 1

loveboat
loveboat

Reputation: 36

Unless this was some cut-n-paste error, I believe this:

mock.count.side_effect = [20, 6, 2]
mock.find.side_effect = [{user: xx}]

Should be:

mocked_collection.count.side_effect = [20, 6, 2]
mocked_collection.find.side_effect = [{user: xx}]

Upvotes: 0

Related Questions