【问题标题】:Python-mock: mocking pymongo's Cursor and Collection in the same test casePython-mock:在同一个测试用例中模拟 pymongo 的 Cursor 和 Collection
【发布时间】:2016-01-29 12:43:46
【问题描述】:

我想对一些 mongo 查询进行模拟测试,但是当我尝试在同一范围内模拟两个不同的 mongo 对象(Cursor 和 Collection)时遇到了问题。 我不能把原始代码放在这里,但我做了一个通用的有同样问题的。

这是我要测试的函数(使用 find 和 distinct):

def get_some_info(date1, date2):
    data = collection.find({"timestamp": {"$lt": date1, "$gt": date2})
    id_list = data.distinct("id")

    for id in id_list :
       collection.find({"id" : id})

这是测试代码:

@mock.patch.object(Collection, "find")
@mock.patch.object(Cursor, "distinct")
def test_get_some_info(self, mock_distinct, mock_find):
    date1 = datetime.datetime()
    date2 = datetime.datetime()
    mock_distinct.return_value = ["id1", "id2"]
    find_parameters1 = {"timestamp": {"$lt": date1, "$gt": date2}
    find_parameters2 = {"id" : "id1"}
    self.my_class.get_some_info(date1, date2)
    mock_find.assert_called_with(find_parameters1)
    mock_find.assert_any_call(find_parameters2)

当我运行测试时,我收到以下错误消息:

'%s call not found' % expected_string AssertionError: find({"id" : "id1"}) 调用未找到

所以我打印了 id_list 的值:

def get_some_info(date1, date2):
    data = collection.find({"timestamp": {"$lt": date1, "$gt": date2})
    id_list = data.distinct("id")
    print id_list

    for id in id_list :
        collection.find({"id" : id})

这是 id_list 的值:

MagicMock name='find().distinct()' id='139719585597776'

但预期是:["id1", "id2"]

当我评论Cursor的mock时,id_list的值和之前一样:

#@mock.patch.object(collection, "distinct")
@mock.patch.object(Cursor, "find")
def test_get_some_info(self, mock_find):
    date1 = datetime.datetime()
    date2 = datetime.datetime()
    mock_distinct.return_value = ["id1", "id2"]
    find_parameters1 = {"timestamp": {"$lt": date1, "$gt": date2}
    find_parameters2 = {"id" : "id1"}
    self.my_class.get_some_info(date1, date2)
    mock_find.assert_called_with(find_parameters1)
    mock_find.assert_any_call(find_parameters2)

<MagicMock name='find().distinct()' id='140089689306448'>

我认为代码总是从 Collection 中捕获“不同”值,而不是从 Cursor 中。 有人遇到同样的问题吗?

【问题讨论】:

    标签: python mongodb mocking pymongo python-mock


    【解决方案1】:
    1. 测试参数中的模拟对象应该是相反的顺序(查看Nesting Patch Decorators了解详细信息)
    2. 你所谓的mock_collection应该是mock_find

    你的测试代码应该是这样的:

    @mock.patch.object(Cursor, "distinct")
    @mock.patch.object(Collection, "find")
    def test_get_some_info(self, mock_find, mock_distinct):
        date1 = datetime.datetime()
        date2 = datetime.datetime()
        mock_distinct.return_value = ["id1", "id2"]
        find_parameters1 = {"timestamp": {"$lt": date1, "$gt": date2}
        find_parameters2 = {"id" : "id1"}
        self.my_class.get_some_info(date1, date2)
        mock_find.assert_called_with(find_parameters1)
        mock_find.assert_any_call(find_parameters2)
    

    【讨论】:

    • 谢谢你的回答,这是我的错误。在我的原始代码中,装饰器的顺序是正确的。我现在更改了参数
    • @DiegoPereira 请解释一下mock_connection 在您的示例中是什么
    • 看看你的日志:connection 是一个模拟,你调用find 的模拟方法
    • 又是我的错,mock_collection是原始源代码中的mock_find。我修好了它。我认为这个问题更多地与“不同”有关,既是 Cursor 的方法,又是 Collection 的方法。再次感谢您的回答。
    • 你的日志说 data.distinct("id") 是一个模拟,其中名称是 find().distinct(),这意味着 data 是 find() 在模拟上的返回值 -> 在 get_some_info() collection 是模拟。现在在您发布的代码中,我无法理解 collection 是什么以及为什么它是模拟的。这就是为什么我们应该避免在我们的问题中发布玩具代码。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-08-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-07
    • 1970-01-01
    相关资源
    最近更新 更多