模拟全局变量 [英] Mocking a global variable
问题描述
我一直在尝试为模块实施一些单元测试.名为 alphabet.py 的示例模块如下:
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'))
我已经看到很多例子,其中补丁"应用于方法和类,而不应用于变量.我不希望修补 database.get 方法,因为稍后我可能会再次将其与不同的参数一起使用,因此我将需要不同的响应.
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.
我在做什么错了?
推荐答案
尝试一下:
import unittests
import alphabet
from unittest.mock import patch
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'))
您需要在单个测试实际运行时应用模拟,而不仅仅是在setUp()
中.我们可以在setUp()
中创建该模拟,然后在以后的with ...
上下文管理器中将其应用.
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.
这篇关于模拟全局变量的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!