2

I'm trying to implement some unittests to validate a method that contains a for loop. This method receives a list of items and for each one of them it executes a function foo() with the item as a parameter.

Does anyone know how can I mock the foo() function to dynamically provide the mocked returned value depending on the element provided as input?

The methods:

def foo(i):
    if i == 'this':
        return 'a'
    else:
        return 'b'

def bar(items):
    results = []
    for item in items:
        results.append(foo(item))
    return results

The unittest:

from unittest import TestCase
from mock import patch

class TestCaseBar(TestCase):

    @patch('my_module.foo')
    def test_bar(self, mock_foo):
        mock_foo.return_value = 'dummy'  # I would like to dinamically mock this.
        items = ['this', 'that']
        result = bar(items)
        self.assertEqual(result, ['a', 'b'])
        self.assertTrue(mock_foo.call_count, 2)
    

Thanks in advance for your answers.

3
  • 1
    You could write your own mocked foo function (which will look like the example you show) and use it as a mock. Commented Oct 20, 2020 at 11:08
  • @MrBeanBremen Could you provide an example? I'm not sure if I should assign the mocked function to mock_foo.return_value or to mock_foo directly. Commented Oct 20, 2020 at 11:24
  • 1
    There already is an answer now, but FWIW, that would be @patch('my_module.foo, my_foo), if my_foo is your function. Using side_effect as shown in the answer is another possibility. Commented Oct 20, 2020 at 12:46

1 Answer 1

5

You could use assign a function to the side_effect property for a mock object. Then, you can implement the mocked details for it.

A function to be called whenever the Mock is called. See the side_effect attribute. Useful for raising exceptions or dynamically changing return values.

E.g.

my_module_64443736.py:

def foo(i):
    if i == 'this':
        return 'a'
    else:
        return 'b'


def bar(items):
    results = []
    for item in items:
        results.append(foo(item))
    return results

test_my_module_64443736.py:

from unittest import TestCase, main
from unittest.mock import patch
from my_module_64443736 import bar


class TestCaseBar(TestCase):

    @patch('my_module_64443736.foo')
    def test_bar(self, mock_foo):
        def dynamicMock(i):
            if i == 'this':
                return 'teresa teng'
            else:
                return 'best singer'
        mock_foo.side_effect = dynamicMock
        items = ['this', 'that']
        result = bar(items)
        self.assertEqual(result, ['teresa teng', 'best singer'])
        self.assertTrue(mock_foo.call_count, 2)


if __name__ == '__main__':
    main()

unit test result:

.
----------------------------------------------------------------------
Ran 1 test in 0.000s

OK
Name                                                    Stmts   Miss  Cover   Missing
-------------------------------------------------------------------------------------
src/stackoverflow/64443736/my_module_64443736.py            9      3    67%   2-5
src/stackoverflow/64443736/test_my_module_64443736.py      16      0   100%
-------------------------------------------------------------------------------------
TOTAL                                                      25      3    88%
Sign up to request clarification or add additional context in comments.

1 Comment

Thumbs up for Teresa Teng!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.