如何模拟MongoClient进行python单元测试?

时间:2014-02-26 09:59:05

标签: python mongodb class mocking

我有一段代码给UT,这让我陷入困境:

  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

我编写以下测试用例来覆盖上面的函数,希望得到返回值“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()

但这永远不会奏效!它始终报告“初始化中的异常!”!并返回“False”。

我怎么能UT这个MongoClient并让函数返回“True”?

3 个答案:

答案 0 :(得分:1)

由于您是单元测试而不是尝试以任何方式实际连接到Mongo,我认为您应该只关心已调用客户端API。所以我建议如下 -

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

(请原谅我,如果我的语法关闭,我使用pytest而不是unittest。)

答案 1 :(得分:0)

简单地传递initialize(),我们可以如下模拟pymongo.MongoClient:

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)

但是我不确定你是在试图模仿MongoClient还是仅仅是MongoClient。 init 部分?

答案 2 :(得分:0)

MongoClient并非旨在以这种方式进行模拟。它必须在__init__中初始化其属性才能运行,所以如果你跳过调用__init__,所有进一步的操作都会抛出各种异常。在您的特定情况下,MongoClient需要访问__slave_okay属性,但未设置。

设置一个实际的MongoDB服务器并对其进行测试,或者使用假库模拟所有PyMongo。简单地覆盖PyMongo中的一些方法并不会有合理的努力。