python unit test with mock for checking file path - python

I have following python function in 'au.py' :
import os
def resolv_conf_audit():
ALT_PATH = "/etc/monitor/etc/resolv.conf.{}".format(os.uname()[1])
RES_PATH = "/data/bin/resolvconf"
if os.path.isfile(RES_PATH):
return "PASSED", "/data/bin/resolvconf is present"
elif os.path.isfile(ALT_PATH):
return "PASSED", "/etc/monitor/etc/resolv.conf. is present"
else:
return "FAILED"
I need to write a unit test with mock which can check the path exists or not
following is the unit test which I wrote
from au import resolv_conf_audit
import unittest
from unittest.mock import patch
class TestResolvConf(unittest.TestCase):
#patch('os.path.isfile.ALT_PATH')
def test_both_source_files_not(self, mock_os_is_file):
mock_os_is_file.return_value = False
assert resolv_conf_audit() == "FAILED"
but I am getting following error
AttributeError: <function isfile at 0x10bdea6a8> does not have the attribute 'ALT_PATH'
How do I mock to check the presence of ALT_PATH and RES_PATH so that I can validate the function. In future this unit test should have the capability to mock removal some files, before writing that I am testing this simple one

Thanks # Mauro Baraldi, as per your suggestion, I changed the code little bit and it works fine now
def test_both_source_files_not(self, mock_os_is_file):
mock_os_is_file.side_effect = [False , False]
assert resolv_conf_audit() == "FAILED"

Mocks by definition is a way to simulate beahvior of objects. You are trying to handle a variable (ALT_PATH) inside your function.
All you need is to mock just the os.path.isfile method.
class TestResolvConf(unittest.TestCase):
#patch('os.path.isfile')
def test_both_source_files_not(self, mock_os_is_file):
mock_os_is_file.return_value = False
assert resolv_conf_audit() == "FAILED"
#patch('os.path.isfile')
def test_both_source_files_exists(self, mock_os_is_file):
mock_os_is_file.return_value = True
assert resolv_conf_audit() == "PASSED"

Related

How to mock a function which makes a mutation on an argument that is necessary for the caller fuction logic

I want to be able to mock a function that mutates an argument, and that it's mutation is relevant in order for the code to continue executing correctly.
Consider the following code:
def mutate_my_dict(mutable_dict):
if os.path.exists("a.txt"):
mutable_dict["new_key"] = "new_value"
return True
def function_under_test():
my_dict = {"key": "value"}
if mutate_my_dict(my_dict):
return my_dict["new_key"]
return "No Key"
def test_function_under_test():
with patch("stack_over_flow.mutate_my_dict") as mutate_my_dict_mock:
mutate_my_dict_mock.return_value = True
result = function_under_test()
assert result == "new_value"
**Please understand i know i can just mock os.path.exists in this case but this is just an example. I intentionally want to mock the function and not the external module.
**
I also read the docs here:
https://docs.python.org/3/library/unittest.mock-examples.html#coping-with-mutable-arguments
But it doesn't seem to fit in my case.
This is the test i've written so far, but it obviously doesn't work since the key changes:
def test_function_under_test():
with patch("stack_over_flow.mutate_my_dict") as mutate_my_dict_mock:
mutate_my_dict_mock.return_value = True
result = function_under_test()
assert result == "new_value"
Thanks in advance for all of your time :)
With the help of Peter i managed to come up with this final test:
def mock_mutate_my_dict(my_dict):
my_dict["new_key"] = "new_value"
return True
def test_function_under_test():
with patch("stack_over_flow.mutate_my_dict") as mutate_my_dict_mock:
mutate_my_dict_mock.side_effect = mock_mutate_my_dict
result = function_under_test()
assert result == "new_value"
How it works is that with a side effect you can run a function instead of the intended function.
In this function you need to both change all of the mutating arguments and return the value returned.

How to mock a function with specific parameter and return value that calls another function in python unit test?

i am new to python unit testing. Want to mock a function that calls other functions.
Here is my function that i want to mock
def has_groups(self, group_names):
auth_user_id = AuthUser.get_by_email(self.userEmail).id
auth_user_groups = AuthUserGroups.get_group_by_user_id(auth_user_id)
for auth_user_group in auth_user_groups:
if auth_user_group.group.name in group_names:
return True
return False
has_groups should return True only when it get's 'Admin' as parameter.
Here is my test
def my_test(self):
uid = self.auth_user.get_by_email = Mock(return_value=73)
groups = AuthUserGroups.get_group_by_user_id = Mock(uid, return_value='Admin')
self.auth_user.has_groups = Mock(groups, return_value=True)
but it's not working fine. I will appreciate if anyone help me
Can i use patch decorator for this and how?
As I understand your has_groups function is method. I think it's better to mock whole class or independent function. On this situation you could mock AuthUserGroups, method return value and patch module with has_groups method implementation. So you'll have test like this:
from unittest import mock
def my_test(self):
group = mock.MagicMock()
group.group.name = 'Admin'
fake_auth_user_groups = mock.MagicMock()
fake_auth_user_groups.get_group_by_user_id.return_value = [group]
with mock.patch('your_module.AuthUserGroups', fake_auth_user_groups):
self.auth_user.has_groups(['Admin'])

Unittest - Test for dict equality

I am trying to do a unit-test but don't quite get why these 2 dicts show up as not equal. I was wondering if someone could give me an explanation for this occurrence. My code is...
import unittest
class TestEmailValidator(unittest.TestCase):
def test(self):
known_dict = {
'debo#foobar.com': True,
'debo#gmail.com': False
}
result_dict = {}
for key in known_dict.keys():
result_dict[key] = is_email_valid(key)
# debugger results
# result_dict = {
# 'debo#foobar.com': True,
# 'debo#gmail.com': False
# }
if self.assertEqual(known_dict, result_dict):
print "is_email_valid passed"
else:
print "is_email_valid failed"
if __name__ == '__main__':
unittest.main()
I get the same result for assertEqual, assertEquals and assertDictEquals. I have tried assigning result_dict to known_dict before the test, but that did not pass either.
It would be great if someone could point me to why this could be happening.
You are misusing the assert. All the assertXYZ methods don't return a boolean value, they just raise an exception if the assertion fails. As these methods don't return anything, they implicitly return None. When evaluating None as a boolean it's treated as false, and hence your test prints is_email_valid failed, even though the test actually passes.

Python Mock function return always False

I try to add unit test in python in function that save stats in a file
Here is the function for saving
def save_file_if_necessary(file_path, content, current_time, mode="w", delta_time=60, force=False):
if file_path not in file_save or current_time - file_save[file_path] >= delta_time or force:
with codecs.open(file_path, mode, encoding="utf-8") as written_file:
written_file.write(content)
file_save[file_path] = time.time()
print "yes"
return True
else:
print "not necessary"
return False
I make a call of this function like that
def test_function():
bot_url_dic = {"seven1": 10,
"seven2": 20
}
save_file_if_necessary(os.path.join("./", "recipients.bots"),json.dumps(bot_url_dic, ensure_ascii=False, indent=4), time.time())
And i made some unittest with mock to test if the function is called
from test import save_file_if_necessary, test_function
def test_call_save_file_if_necessary(self):
"""test function to test add in list."""
ip_dic = ["seven1", "seven2", "seven3"]
save_file_if_necessary = Mock()
test_function()
self.assertTrue(save_file_if_necessary.called)
But the problem is Mock is always return False but the function is called at least one time.
self.assertTrue(save_file_if_necessary.called)
AssertionError: False is not true
(python version 2.7.6)
All you've done is create a new Mock object, coincidentally called "save_file_if_necessary". You haven't done anything to replace the actual function with your mock.
You need to use the patch functionality to actually do that:
#mock.patch('my_test_module.save_file_if_necessary')
def test_call_save_file_if_necessary(self, mock_function):
ip_dic = ["seven1", "seven2", "seven3"]
test_function()
self.assertTrue(mock_file.called)
You need to import the module where the function is defined and assign a Mock to your function:
import test
def test_call_save_file_if_necessary(self):
"""test function to test add in list."""
ip_dic = ["seven1", "seven2", "seven3"]
test.save_file_if_necessary = Mock()
test.test_function()
self.assertTrue(test.save_file_if_necessary.called)
Or, use the patching function instead.

How to stub method in mocked object?

I need to test code snippet (e.g. from class UnderTestClass):
def _method_to_test(self)
...
ParsingObject = MyParsingClass()
if not ParsingObject.parse_string(some_string):
self.logger.error('Parsing data has failed.')
return False
return ParsingObject
No matter how I try, can't cover last return statement - return ParsingObject, so it have to be something wrong with my mocking of parse_string() method.
I've tried inter alia statements from Python testing tutorial:
from my_app import myParsingClass
...
def test_method_to_test_success(self):
...
UnderTestClassMock = Mock(name='UnderTestClass')
parsePatch = patch('my_app.myParsingClass.MyParsingClass')
parseMock = parsePatch.start()
parseInstance = parseMock.return_value
parseInstance.parse_string.return_value = True
res = tested_module.UnderTestClass._method_to_test(UnderTestClassMock)
parsePatch.stop()
self.assertIsInstance(res, myParsingClass.MyParsingClass)
But unfortunately get only:
AssertionError: False is not an instance of class 'my_app.myParsingClass.MyParsingClass'
UPDATE: Thanks. I follow your advice, so re-write a bit:
with patch('...') as ParseMock:
instance = ParseMock.return_value
ParseMock.parse_string.return_value = True
res = tested_module.UnderTestClass._method_to_test(UnderTestClassMock)
assert myParsingClass.MyParsingClass() is instance
assert myParsingClass.MyParsingClass() is res
but still got AssertionError on last line.
EDIT: do I need somehow dependency injection mechanism/framework?
You need to set return_value on parseMock, not parseInstance:
parseMock.parse_string.return_value = True
Also you need to stop() the patch after your assert
You should mock the instance method parse_string, not the class method.
In [22]: import mock
In [23]: ParseMock = mock.Mock()
In [24]: instance = ParseMock.return_value
In [25]: instance.parse_string.return_value = True
In [26]: parser = ParseMock()
In [27]: parser.parse_string("foo")
Out[27]: True

Categories

Resources