【问题标题】:Python Mock patch ldap3 search responsePython Mock 补丁 ldap3 搜索响应
【发布时间】:2021-01-06 01:56:42
【问题描述】:

我正在尝试模拟以下函数,但我不确定如何模拟连接响应:

def get_user_res(user, pass):
    res = None
    server = Server('my_server')
    connnection = Connection(server, user, pass, strategy=SAFE_SYNC, auto_bind=True)
    if connection.bind():
        connection.search(search_base, search_filter, SUBTREE)
        res = connection.response
        connection.unbind()
    return res
@mock.patch("ldap3.Server")
@mock.patch("ldap3.Connection.response")
def test_get_user_res(mock_connection, mock_server):
    mock_connection.return_value = ""
    retrived_res = get_user_res("fake_user","fake_password")
    expected_res = ""
    assert retrived_res == expected_res

【问题讨论】:

  • 如果您在提问时发布minimal, reproducible example 会有所帮助。您发布的代码存在语法错误,并且测试使用了您未显示定义的夹具。这让我们很难提供帮助,因为显而易见的答案是“你用太多的 n 拼写了 'connection'”。

标签: python unit-testing python-unittest python-unittest.mock ldap3


【解决方案1】:

根本问题是你在嘲笑错误的东西。如果您有一个名为 ldapclient.py 的文件,其中包含您的 get_user_rest 方法,就像这样(请注意,我已经重写了一些内容以使我们在编写测试时更轻松):

import ldap3

server = ldap3.Server('my_server')
search_base = 'dc=example, dc=com'


def get_user_res(user, password, search_filter=None):
    res = None

    connection = ldap3.Connection(
        server, user, password,
        client_strategy=ldap3.SAFE_SYNC, auto_bind=True)

    if connection.bind():
        res = connection.search(search_base, search_filter, ldap3.SUBTREE)
        connection.unbind()

    return res

那么你需要模拟的是ldap3.Connection 类。但由于您的测试在不同的模块中,您需要调用@mock.patch('ldapclient.ldap3.Connection),假设您的测试是这样定义的:

import ldap3

from unittest import mock

import ldapclient


@mock.patch("ldapclient.ldap3.Connection")
def test_get_user_res(mock_connection_class):
    mock_connection = mock.Mock()
    mock_connection.search.return_value = 'fake_return'
    mock_connection_class.return_value = mock_connection

    retrived_res = ldapclient.get_user_res("fake_user", "fake_password")
    expected_res = "fake_return"
    assert retrived_res == expected_res

这里有几点需要注意:

  1. 如前所述,因为我们有import ldapclient,所以我们需要模拟ldapclient.ldap3.Connection
  2. 我们让ldap3.Connection 类返回一个新的mock.Mock 对象,因为我们希望能够模拟调用connection = ldap3.Connection(...) 时返回的对象的方法
  3. 我们让search 方法返回一个假值,以便我们可以确保它按预期被调用。

【讨论】:

  • 感谢您的帮助!我还有一个问题。如何更改 mock_connection.search.return_value 以返回 json 对象?因为当我试图在 main 函数中解析 response[0]['attributes']['displayname'] 时,它返回的 Mock 对象不可下标。我在 connection.search() 中传递 attributes=["displayname"]。
  • 您将返回值设置为您想要的任何值。例如,如果你希望它返回一个列表或字典(我认为你的意思是“JSON 对象”),你可以设置 mock_connection.search.return_value = [{'attributes': {'displayname': 'foo'}}]
  • 非常感谢。我让它工作,但你应该在你的答案中将 mock_connection.search.return_value 更改为 mock_connection.response.return_value。
  • 实际上,如果您查看我的答案中的代码,我从不请求 response 属性,因此对于此示例没有意义。
  • 对此有很好的背景阅读 - 帮助我理解了为什么与上述类似的问题不起作用:nedbatchelder.com/blog/201908/why_your_mock_doesnt_work.html
猜你喜欢
  • 2019-09-12
  • 1970-01-01
  • 2015-06-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 1970-01-01
  • 2012-12-18
相关资源
最近更新 更多