Mocking a Global Variable

Mocking a global variable

Try this:

import unittests  
import alphabet
from unittest import mock


class TestAlphabet(unittest.TestCase):
def setUp(self):
self.mock_letters = mock.patch.object(
alphabet, 'letters', return_value=['a', 'b', 'c']
)

def test_length_letters(self):
with self.mock_letters:
self.assertEqual(3, alphabet.length_letters())

def test_contains_letter(self):
with self.mock_letters:
self.assertTrue(alphabet.contains_letter('a'))

You need to apply the mock while the individual tests are actually running, not just in setUp(). We can create the mock in setUp(), and apply it later with a with ... Context Manager.

How to mock an uninitialized global variable?

I used the setUp and tearDown methods on the unittest.TestCase class to solve this.

With my edit above about it actually being a config object the code looks like this:

class Config:
def __init__(self, filename: str):
"Load config file and set self.stuff"
self.stuff = _code_to_parse(filename)
config: Config
def do_stuff() -> str:
return "a" if config.stuff else "b"

And the test creates a mocked config object before the tests in order to mock some attribute on the config object during the test. In the teardown I also delete the object again so that nothing will spill to the next test case.

The actual mocking of the attributes I need is then done in a with block in the actual test as it is (a) cleaner and (b) I can just mock what I need in contrast to mocking all attributes on the config object in the setUp method.

import unittest, unittest.mock, mod
class MockUninitializedGlobal(unittest.TestCase):
def setUp(self):
mod.config = unittest.mock.Mock(spec=mod.Config)
def tearDown(self):
del mod.config
def test_it(self):
with unittest.mock.patch("mod.config.stuff", True):
actual = mod.do_stuff()
expected = "a"
self.assertEqual(expected, actual)


Related Topics



Leave a reply



Submit