我很乐意承认单元测试会有点过分。 虽然我通过测试,但我觉得我的解决方案不够优雅,如果有人有更清洁的解决方案,我很好奇。
正在测试的课程:
class Config():
def __init__(self):
config_parser = ConfigParser()
try:
self._read_config_file(config_parser)
except FileNotFoundError as e:
pass
self.token = config_parser.get('Tokens', 'Token', )
@staticmethod
def _read_config_file(config):
if not config.read(os.path.abspath(os.path.join(BASE_DIR, ROOT_DIR, CONFIG_FILE))):
raise FileNotFoundError(f'File {CONFIG_FILE} not found at path {BASE_DIR}{ROOT_DIR}')
丑陋的考验:
class TestConfiguration(unittest.TestCase):
@mock.patch('config.os.path.abspath')
def test_config_init_sets_token(self, mockFilePath: mock.MagicMock):
with open('mock_file.ini', 'w') as file: #here's where it gets ugly
file.write('[Tokens]\nToken: token')
mockFilePath.return_value = 'mock_file.ini'
config = Config()
self.assertEqual(config.token, 'token')
os.remove('mock_file.ini') #quite ugly
编辑:我的意思是我创建一个文件而不是嘲笑文件。
有没有人知道如何mock
一个文件对象,同时拥有它的数据集,以便它读取ascii文本?这堂课深受埋葬。
除此之外,ConfigParser
使用.read()
设置数据的方式让我失望。当然,测试"工作",它没有做得很好。
对于那些询问其他测试行为的人,这里有另一个测试的例子:
@mock.patch('config.os.path.abspath')
def test_warning_when_file_not_found(self, mockFilePath: mock.MagicMock):
mockFilePath.return_value = 'mock_no_file.ini'
with self.assertRaises(FileNotFoundError):
config.Config._read_config_file(ConfigParser())
感谢您的时间。
答案 0 :(得分:1)
我找到了它!
我不得不从一些导入开始:from io import TextIOWrapper, BytesIO
这允许创建文件对象:TextIOWrapper(BytesIO(b'<StringContentHere>'))
下一部分涉及深入configparser
模块以查看它调用open()
,以便mock.patch
行为,并且,在这里我们拥有它,一个独立的单元测试!< / p>
@mock.patch('configparser.open')
def test_bot_init_sets_token(self, mockFileOpen: mock.MagicMock):
mockFileOpen.return_value = TextIOWrapper(BytesIO(b'[Tokens]\nToken: token'))
config = Config()
self.assertEqual(config.token, 'token')