Mocking a global variable

Funkatic picture Funkatic · Jul 12, 2016 · Viewed 57.8k times · Source

I've been trying to implement some unit tests for a module. An example module named alphabet.py is as follows:

import database

def length_letters():
    return len(letters)

def contains_letter(letter):
    return True if letter in letters else False


letters = database.get('letters')   # returns a list of letters

I'd like to mock the response from a database with some values of my choice, but the code below doesn't seem to work.

import unittests  
import alphabet   
from unittest.mock import patch   


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

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

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

I have seen many examples in which 'patch' is applied to methods and classes, but not to variables. I prefer not to patch the method database.get because I may use it again with different parameters later on, so I would need a different response.

What am I doing wrong here?

Answer

Valera Maniuk picture Valera Maniuk · Jul 28, 2018

Variables can be patched as follows:

from mock import patch
@patch('module.variable', new_value)    

For example:

import alphabet
from mock import patch
@patch('alphabet.letters', ['a', 'b', 'c'])
class TestAlphabet():

    def test_length_letters(self):
        assert 3 == alphabet.length_letters()

    def test_contains_letter(self):
       assert alphabet.contains_letter('a')