简体   繁体   English

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

[英]How to mock MongoClient for python unit test?

I have following piece of code to UT, which makes me in trouble: 我将以下代码发送给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

I write following test case to cover the above function, hope to get return value "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()

But this never works! 但是,这永远行不通! It always report "Exception in initialize!"! 它总是报告“初始化异常!”! and return "False". 并返回“ False”。

How could I UT this MongoClient and makes the function return "True"? 我如何才能使用此MongoClient并使函数返回“ 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. 由于您正在进行单元测试,并且不尝试以任何方式实际连接到Mongo,因此我认为您应该只关心已调用客户端API。 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.) (如果我的语法关闭,请原谅我,我使用pytest而不是unittest。)

For simply pass the initialize(), we can mock the pymongo.MongoClient as following: 为了简单地传递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)

However I'm not sure if you're trying to mock the MongoClient or just the MongoClient. 但是我不确定您是要模拟MongoClient还是仅模拟MongoClient。 init part? 初始化部分?

MongoClient is not designed to be mocked this way. MongoClient并非旨在以这种方式被嘲笑。 It must initialize its attributes in __init__ in order to function, so if you skip calling __init__ , all further operations will throw various exceptions. 它必须在__init__中初始化其属性才能起作用,因此,如果您跳过调用__init__ ,则所有其他操作都将引发各种异常。 In your specific case, MongoClient needs access to the __slave_okay attribute, but it isn't set. 在您的特定情况下,MongoClient需要访问__slave_okay属性,但未设置。

Either set up an actual MongoDB server and test against it, or mock all of PyMongo with a fake library. 设置一个实际的MongoDB服务器并对其进行测试,或者使用一个伪造的库模拟所有PyMongo。 Simply overriding a handful of methods in PyMongo is not going to work with reasonable effort. 仅仅在PyMongo中覆盖少数方法是不可行的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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