4

So I've this code that mocks two times, the first time by mocking imports with:

sys.modules['random'] = MagicMock()

The second time happens inside the unittest of a function that used that import, for example a function that used random

The tests. py is:

import sys
import unittest
from unittest import mock
from unittest.mock import MagicMock
import foo

sys.modules['random'] = MagicMock()

class test_foo(unittest.TestCase):

    def test_method(self):
        with mock.patch('random.choice', return_value = 2):
            object = foo.FooClass(3)
            self.assertEqual(2, object.method(), 'Should be 2')

    def test_staticmethod(self):
        with mock.patch('random.choice', return_value = 2):
            object = foo.FooClass(3)
            self.assertEqual(2, object.method(), 'should be 2')

The original file Foo.py is:

import random

class FooClass:

    def __init__(self,arg):
        self.arg = arg

    def method(self):
        print(random.choice)
        return random.choice([1,2,3])

    @staticmethod
    def staticmethod():
        print(random.choice)
        random.choice([1,2,3])

The two mocks contrarrest each other, and the mocking of random doesn't happen. When it prints random it actually prints:

<<bound method Random.choice of <random.Random object at 0x7fe688028018>>

I want that to print a MagicMock. Can someone help me understand what's happening? Why are they contrarresting each other?

  • 1
    Can you explain why you need that double mocking, and what happens in your test? Also, you have `self` in your static function - probably just a typo. – MrBean Bremen Aug 15 '20 at 08:37
  • I'm trying to create automatic unit tests, the way that I'm doing it does so two times, one at the beggining trying to mock the imported libraries, and the other one mocks inside the proper unit tests using with mock patch. I know this could be problematic, however it is working for all of the functions except the static ones. When I print the mocked object inside the test it prints the module random, and not it's mock, I don't know why it only happens with staticmethods. – Fabiola Jiménez-González Aug 15 '20 at 15:48
  • Hm, it would probably help if you could show a bit more code. So you are saying that mocking random using `mock.patch` works if you test the static function, but if you additionally mock `sys.modules` it stops to work? – MrBean Bremen Aug 15 '20 at 15:53
  • Yeah MrBean, exactly that happens, I edited the question to provide you with more code information – Fabiola Jiménez-González Aug 15 '20 at 20:57
  • Ok, at a first guess I would say that the patching in the first test (more exactly ending the patching) is restoring the original value in `sys.modules`, because this is how it works. You can verify that by commenting out the first test. Still unclear why you need changing `sys.modules` in the first place. – MrBean Bremen Aug 15 '20 at 22:11

1 Answers1

1

You don't need to update the module source with sys.modules['random'] = MagicMock() without this line it works fine <MagicMock name='choice' id='...'>. patch already does all the work for the isolated temporary updating the method. See more explanation in the docs - Where to patch

Yann
  • 2,426
  • 1
  • 16
  • 33