如何使用pytest-mock模拟一个类并使用py.test控制返回的值?

时间:2016-12-19 05:20:50

标签: python mocking pytest

我正在尝试使用py.test来测试执行各种LDAP搜索和修改的代码。

我正在使用pytest-mock,但我无法理解如何模拟LDAP对象的创建,并控制在模拟对象上调用search_s()时返回的内容

我认为这会做我想要的,但测试失败,计数显示生成器函数find_users()永远不会产生任何结果。

import pytest
# Here is some code to simply test mocking out ldap.initialize(), and
# controlling the return value from calls to search_s()
import ldap

def find_users(ldap_url, admin_user, admin_password, userbase):
    lobj = ldap.initialize(ldap_url)
    lobj.simple_bind_s(admin_user, admin_password)
    for i in lobj.search_s(userbase, ldap.SCOPE_SUBTREE, '*'):
        yield i[1]['uid'][0]

class TestMocking:

    @pytest.fixture()
    def no_ldap(self, mocker):
        return mocker.patch('ldap.initialize')


    def test_ad_one_user(self, no_ldap):
        # try and modify how search_s() would return
        no_ldap.search_s.return_value = ('', {'uid': ['happy times']})
        count = 0 
        for i in find_users('', '', '', ''):
            count += 1
            assert i=='happy times'
        assert count == 1

2 个答案:

答案 0 :(得分:2)

你可以直接使用补丁(关于你的结构的一些东西):

from mock import patch, Mock
import pytest
# Here is some code to simply test mocking out ldap.initialize(), and
# controlling the return value from calls to search_s()
import ldap

def find_users(ldap_url, admin_user, admin_password, userbase):
    lobj = ldap.initialize(ldap_url)
    lobj.simple_bind_s(admin_user, admin_password)
    for i in lobj.search_s(userbase, ldap.SCOPE_SUBTREE, '*'):
        yield i[1]['uid'][0]

class TestMocking:

    @patch('ldap.initialize')
    def test_ad_one_user(self, no_ldap):
        # try and modify how search_s() would return
        data = [('', {'uid': ['happy times']})]
        search_s = Mock(return_value=data)
        no_ldap.return_value = Mock(search_s=search_s)
        count = 0
        for i in find_users('', '', '', ''):
            count += 1
            assert i=='happy times'
        assert count == 1

答案 1 :(得分:1)

我认为你可能会在https://docs.python.org/3/library/unittest.mock.html和pytest mockey补丁之间感到困惑。我不认为两者的行为方式相同。

您可以使用模拟补丁来使其工作 (https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch

@pytest.fixture()
def no_ldap(self):
    patcher = mock.patch('ldap.initialize')
    patcher.start()
    yield patcher
    patcher.stop()