1

My python file has many methods defined in it. In many of the methods in the file, I am calling a function - let's say "fun1".

I want to mock the 'fun1' function for each of the methods differently. Is there a way to patch an object differently at method level and not at file level?

 Contents of aPythonFile.py
=======================================
    import fun from a_module

    def a():
        res= fun(aarg1, aarg2)
        return res

    def b():
        res = fun(barg1, barg2)
        return res

This came to my mind, as I know, the same "fun" can be patched differently for different files, then why not be able to patch differently based on the method in the file where it is called :-

@mock.patch("package.aPythonFile.fun") - Is Valid

@mock.patch("package.aPythonFile.a.fun") - ?? (possible?)
@mock.patch("package.aPythonFile.b.fun") - ?? (possible?)
7
  • This answer ( stackoverflow.com/questions/15753390/…) is not answering my question. What is suggested there is already known and followed by me. For my case, I want to organize the code more cleanly which this current approach (or the one referred as duplicate) is not providing! Commented Mar 19, 2021 at 12:01
  • I am not sure what you are getting at. @mock.patch applies to an individual test method, so if you have a test_a and test_b, they can be patched with different methods. You do realize one of the answers in that thread literally has the mocking done at the method level, you can just change the argument passed to side_effect to the method you specifically require for the specific test... Commented Mar 19, 2021 at 12:46
  • It would then be useful to include how you are currently testing that aPythonFile.py of yours. Your edited code has only make your question even more confusing. You need to show clearly what you are doing. If you want different return values for fun1 that were called throughout an execution you may wish to refer to this thread. In any case please clean up your question because as it is now is quite unclear on what you are asking, but at least you made it not obviously a duplicate of the other question, though as is it is still unanswerable. Commented Mar 19, 2021 at 14:39
  • Ok thanks, I have edited it (hopefully its more clear). I am new with testing in python, but when I am learning about mock(ing) with inbuilt unit test, I feel that it is quite common that the object which is being mocked could be called several times in a file in practical scenario. I see that the module 'unittest.mock' allows an object to patch differently per file level in a package, then why not there is a way to patch an object, for example - able to patch it differently based on the method in which it is being in the file Commented Mar 19, 2021 at 16:56
  • 1
    It's possible. Mock the function with side_effect replacement function. Inside your side_effect function, get the function name of caller, then do different code based on which caller is it. Alternatively, instead of caller name you can vary behaviour based on argument values instead. Commented Mar 19, 2021 at 18:29

1 Answer 1

0

Just provide different mock_fun.return_value for each test case.

E.g.

a_module.py:

def fun(a, b):
    pass

a_python_file.py:

from a_module import fun


def a():
    res = fun('a1', 'a2')
    return res


def b():
    res = fun('b1', 'b2')
    return res

test_a_python_file.py:

import unittest
from unittest import mock
from a_python_file import a, b


class TestAPythonFile(unittest.TestCase):
    @mock.patch('a_python_file.fun')
    def test_a(self, mock_fun):
        mock_fun.return_value = 'return value for a'
        actual = a()
        self.assertEqual(actual, 'return value for a')

    @mock.patch('a_python_file.fun')
    def test_b(self, mock_fun):
        mock_fun.return_value = 'return value for b'
        actual = b()
        self.assertEqual(actual, 'return value for b')


if __name__ == '__main__':
    unittest.main()

unit test result:

⚡  coverage run /Users/dulin/workspace/github.com/mrdulin/python-codelab/src/stackoverflow/66707457/test_a_python_file.py && coverage report -m --include='./src/**'  
..
----------------------------------------------------------------------
Ran 2 tests in 0.001s

OK
Name                                               Stmts   Miss  Cover   Missing
--------------------------------------------------------------------------------
src/stackoverflow/66707457/a_module.py                 2      1    50%   2
src/stackoverflow/66707457/a_python_file.py            7      0   100%
src/stackoverflow/66707457/test_a_python_file.py      16      0   100%
--------------------------------------------------------------------------------
TOTAL                                                 25      1    96%
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.