简体   繁体   中英

How to mock MongoClient for python unit test?

I have following piece of code to UT, which makes me in trouble:

  def initialize():
    try :
        self.client = MongoClient("127.0.0.1", 27017)
        self.conn = self.client["DB_NAME"]
    except Exception:
        print "Except in initialize!"
        return False
    return True

I write following test case to cover the above function, hope to get return value "True":

def mock_mongodb_mongoclient_init(self, para1, para2):
    pass

def mock_mongodb_mongoclient_getitem(self, name):
    return {"DB_NAME":"Something"}

def test_mongodb_initialize_true(self):
    self.patcher1 = patch('pymongo.MongoClient.__init__', new=self.mock_mongodb_mongoclient_init)
    self.patcher2 = patch('pymongo.MongoClient.__getitem__', new=self.mock_mongodb_mongoclient_getitem)
    self.patcher1.start()
    self.patcher2.start()
    self.assertEqual(initialize(), True)
    self.patcher1.stop()
    self.patcher2.stop()

But this never works! It always report "Exception in initialize!"! and return "False".

How could I UT this MongoClient and makes the function return "True"?

Since you are unit testing and not trying to actually connect to Mongo in any way, I think you should just care that the client API has been called. So I would suggest the following -

from unittest import mock
@mock.patch("pymongo.MongoClient")
def test_mongodb_initialize(self, mock_pymongo):
    MyMongo.initialize()
    self.assertTrue(mock_pymongo.called)

(Forgive me if my syntax is off, I use pytest rather than unittest.)

For simply pass the initialize(), we can mock the pymongo.MongoClient as following:

import unittest
import pymongo
from mock import patch


class MyMongo(object):
    def initialize(self):
        try :
            self.client = pymongo.MongoClient("127.0.0.1", 27017)
            self.conn = self.client["DB_NAME"]
        except Exception:
            print "Except in initialize!"
            return False
        return True


class TestMyMongo(unittest.TestCase):
    def test_mongodb_initialize_true(self):
        with patch('pymongo.MongoClient') as mock_mongo:
            self.mymongo = MyMongo()
            self.assertEqual(self.mymongo.initialize(), True)

However I'm not sure if you're trying to mock the MongoClient or just the MongoClient. init part?

MongoClient is not designed to be mocked this way. It must initialize its attributes in __init__ in order to function, so if you skip calling __init__ , all further operations will throw various exceptions. In your specific case, MongoClient needs access to the __slave_okay attribute, but it isn't set.

Either set up an actual MongoDB server and test against it, or mock all of PyMongo with a fake library. Simply overriding a handful of methods in PyMongo is not going to work with reasonable effort.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM