当从另一个函数调用mongodb时,如何模拟它? - python

我在模拟mongodb时需要帮助。我正在使用mongomock模拟mongodb。

我的项目结构是:

  -my_mongo.py
  -code.py
  -my_test.py

my_mongo.py具有:

from pymongo import MongoClient

 def get_db():
   client = MongoClient(os.environ['MONGODB_URI'])
   db = client['my_db']
   return db

 def insert(id, data):
     return get_db().results.insert_one(
          {
          "id": id,
          "data":df.to_json(),
          }).id

和code.py有

import my_mongo

def action():
    #do somethings
    my_mongo.insert(id, data)

和my_test.py有

import mongomock
import my_mongo
from unittest import mock


with patch.object(my_mongo.get_db().client, "client",  mongomock.MongoClient()):
    import code

def test_action_1():
    my_mongo.insert = mock.Mock(return_value=1)
    code.action()   

def test_action_2():
     with patch.object(my_mongo.get_db(), "get_db", mongomock.MongoClient().db):
     code.action()

两种测试都会抛出pymongo.errors.ServerSelectionTimeoutError。因此,它仍然进入my_mongo.py中的insert_one()方法。
我希望在test_action_1中my_mongo.insert返回1,但不会。

我想念什么?

python大神给出的解决方案

我不确定mongomock是什么,但是看起来它是用于模拟整个mongo数据库,而不是实际使用python模拟。我将在不包含mongomock的情况下回答,因为我认为您并非真正需要它,因此您可以以它的价值来接受它。

有几个问题:

调用patch.object将在给定的任何对象上修补给定的方法。如果在测试中调用get_db,则code.action调用get_db,这是2个不同的对象。也许行得通吗?但是我对此表示怀疑,所以我只是更改了它。
不要使用code作为模块名称。那已经是python附带的模块了。
code.action缺少args和return语句。

您还将注意到,我更改了模拟的方式和内容,以说明完成模拟的不同方法。测试1使用函数装饰器模拟insert调用。测试2使用get_db模拟contextmanager调用。两种方法都正确,只是表明您有选择权。

这是成品:

my_mongo.py:

from pymongo import MongoClient

def get_db():
    client = MongoClient(os.environ['MONGODB_URI'])
    db = client['my_db']
    return db

def insert(id, data):
    return get_db().results.insert_one({"id": id, "data":data.to_json()}).id  # df was undefined, updated to data

my_code.py:

import my_mongo

# I added id and data args. They were undefined
def action(id, data):
    return my_mongo.insert(id, data)  # I added a return here

my_test.py

from unittest import mock

import my_code

# I removed the contextmanager import. Nothing is being evaluated here that would
# need to be patched, so I'm pretty certain it has no effect

@mock.patch('my_mongo.insert')
def test_action_1(mock_insert):
    expected_id = 1
    mock_insert.return_value = expected_id
    ret = my_code.action(expected_id, mock.Mock())
    assert ret == expected_id

def test_action_2():
    with mock.patch('my_mongo.get_db') as mock_get_db:
        expected_id = 'some id'
        mock_db = mock.Mock()
        mock_db.results.insert_one.return_value.id = expected_id
        mock_get_db.return_value = mock_db
        ret = my_code.action(expected_id, mock.Mock())
    assert ret == expected_id

Python sqlite3数据库已锁定 - python

我在Windows上使用Python 3和sqlite3。我正在开发一个使用数据库存储联系人的小型应用程序。我注意到,如果应用程序被强制关闭(通过错误或通过任务管理器结束),则会收到sqlite3错误(sqlite3.OperationalError:数据库已锁定)。我想这是因为在应用程序关闭之前,我没有正确关闭数据库连接。我已经试过了: connectio…

Python pytz时区函数返回的时区为9分钟 - python

由于某些原因,我无法从以下代码中找出原因:>>> from pytz import timezone >>> timezone('America/Chicago') 我得到:<DstTzInfo 'America/Chicago' LMT-1 day, 18:09:00 STD…

用大写字母拆分字符串,但忽略AAA Python Regex - python

我的正则表达式:vendor = "MyNameIsJoe. I'mWorkerInAAAinc." ven = re.split(r'(?<=[a-z])[A-Z]|[A-Z](?=[a-z])', vendor) 以大写字母分割字符串,例如:'我的名字是乔。 I'mWorkerInAAAinc”变成…

如何打印浮点数的全精度[Python] - python

我编写了以下函数,其中传递了x,y的值:def check(x, y): print(type(x)) print(type(y)) print(x) print(y) if x == y: print "Yes" 现在当我打电话check(1.00000000000000001, 1.0000000000000002)它正在打印:<…

Python:检查新文件是否在文件夹中[重复] - python

This question already has answers here: How do I watch a file for changes? (23个答案) 3年前关闭。 我是python的新手,但是我尝试创建一个自动化过程,其中我的代码将侦听目录中的新文件条目。例如,某人可以手动将zip文件复制到一个特定的文件夹中,并且我希望我的代码能够在文件完全…