Background
Relatively new to Python and its unittest module. Having trouble mocking a static class variable within test.
(Only when the original class method is referencing its own class variable by its first argument: cls)
Example:
Simplified version of the class and class method being tested:
a.py
class A:
# class variable
my_list = []
@classmethod
def my_method(cls, item):
print cls # [] unable to mock this, why?
print A # [1,2,3] mocked as intended
cls.my_list.append(item)
Test:
import unittest
from mock import patch
from a import A
class Test(unittest.testCase):
def test_my_method(self):
with patch("a.A") as mock_A:
# mocking the class variable
mock_A.my_list = [1,2,3]
# test call class method
A.my_method(4)
# assert the appended list to expected output
self.assertEqual(mock_A.my_list, [1,2,3,4])
# should evaluate to true, but fails the test
if __name__ == "__main__":
unittest.main()
Question:
Why does mock only patches the A reference and not the cls reference?
In what direction should the solution be, in order to successfully patch the cls argument as well, so class method can pass the test shown above.
You imported A
already within the test module, so you already have a reference to the original unpatched A
, and this is what you call my_method
on.
- Why does mock only patches the A reference and not the cls reference?
Because that's what you patched. Patch works by intercepting on name lookups, it doesn't (and can't) literally replace objects in place. When you want to patch out an object that has multiple names (A
and cls
, in this case) then you'd have to patch out every name lookup.
- In what direction should the solution be, in order to successfully patch the cls argument as well, so class method can pass the test shown above.
It will be better to patch out the class attribute directly:
class Test(unittest.TestCase):
def test_my_method(self):
with patch("a.A.my_list", [1,2,3]):
A.my_method(4)
self.assertEqual(A.my_list, [1,2,3,4])
self.assertEqual(A.my_list, []) # note: the mock is undone here