I'm trying to use py.test
to test some code that does various LDAP
searches, and modifications.
I'm using pytest-mock
, but I'm having trouble understanding how to mock out the creation of the an LDAP object, and control what it returns when a search_s()
is called on the mocked object.
I thought this would do what I wanted, but the test fails, the count shows the generator function find_users()
never yields anything.
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
To mock an entire class you'll need to set the return_value to be a new instance of the class. @mock.
To implement mocking, install the pytest-mock Python package. In this example within the src/sample_file.py file, we define the desired function and function to be mocked.
patch() unittest. mock provides a powerful mechanism for mocking objects, called patch() , which looks up an object in a given module and replaces that object with a Mock .
You can just use patch directly (and something was off about your structure):
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
I think you may be getting confused between https://docs.python.org/3/library/unittest.mock.html and pytest monkey patch. I don't think both behave in the same way.
You can make it work using mock patch (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()
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With