Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I mock a function called from a dictionary?

test.py:

@pytest.mark.django_db
def test_b_called(mocker):
    b = mocker.patch('app.service.b')

    service.a('b')
    assert b.called

service.py:

def a(type):
    _actions[type]()

def b():
    pass

_actions = { 'b': b }

My test will fail as my patch does not work as I expected. What am I doing wrong here? This definitely works if a calls b directly and not using that dictionary. I have tested for this. I know you can mock a dictionary with patch.dict but then how would I test that b was called?

like image 211
Pittfall Avatar asked Jan 18 '26 07:01

Pittfall


1 Answers

So I would argue that these are two separate unit tests, one for function a and one for the dictionary _actions.

_actions is not just a simple dictionary but in a sense a dynamic function call. So if you are truly testing just function a then you need to patch the _actions object and just test the functionality in the scope of the function.

_actions is out of the testing scope and should be tested individually like any other method.

from unittest import TestCase
from unittest.mock import patch
from stack_overflow import a,b,c, _actions

class TestStack(TestCase):

    def setUp(self):
        super().setUp()

    def tearDown(self):
        super().tearDown()

    @patch.dict('stack_overflow._actions',{'b':b})
    def test_a(self):
        self.assertEqual(5,a('b'))

    def test__actions_def_b(self):
        self.assertEqual(_actions['b'],b)

    def test__actions_def_c(self):
        self.assertEqual(_actions['c'],c)
def a(type):
    current_actions = _actions
    return _actions[type]()

def b():
    return 5

def c():
    return 7

_actions = { 'b': b, 'c': c}
like image 170
w33b Avatar answered Jan 19 '26 19:01

w33b



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!