ces*_*mba 2 python unit-testing environment-variables python-unittest
我正在尝试测试一个根据给定参数为我处理工作目录的类。为此,我们使用类变量来映射它们。
当传递特定值时,将从环境变量中检索路径(请参见baz下面的示例)。这是我正在尝试测试的具体案例。
我正在使用 Python3.8.13和unittest.
WorkingDirectory.map字典,因为我想确保我们从environ特定变量(BAZ_PATH)中获取。os.environ["baz"] = DUMMY_BAZ_PATH我尝试按照其他出版物中的建议将其模拟environ为字典,但由于某种原因我无法使其工作。
# working_directory.py
import os
class WorkingDirectory:
map = {
"foo": "path/to/foo",
"bar": "path/to/bar",
"baz": os.environ.get("BAZ_PATH"),
}
def __init__(self, env: str):
self.env = env
self.path = self.map[self.env]
@property
def data_dir(self):
return os.path.join(self.path, "data")
# Other similar methods...
Run Code Online (Sandbox Code Playgroud)
测试文件:
# test.py
import os
import unittest
from unittest import mock
from working_directory import WorkingDirectory
DUMMY_BAZ_PATH = "path/to/baz"
class TestWorkingDirectory(unittest.TestCase):
@mock.patch.dict(os.environ, {"BAZ_PATH": DUMMY_BAZ_PATH})
def test_controlled_baz(self):
wd = WorkingDirectory("baz")
self.assertEqual(wd.path, DUMMY_BAZ_PATH)
Run Code Online (Sandbox Code Playgroud)
如错误所示,os.environ返回时似乎没有正确修补Null。
======================================================================
FAIL: test_controlled_baz (test_directory_structure_utils.TestWorkingDirectory)
----------------------------------------------------------------------
Traceback (most recent call last):
File "~/.pyenv/versions/3.8.13/lib/python3.8/unittest/mock.py", line 1756, in _inner
return f(*args, **kw)
File "~/Projects/dummy_project/tests/unit/test_directory_structure_utils.py", line 127, in test_controlled_baz
self.assertEqual(wd.path, DUMMY_BAZ_PATH)
AssertionError: None != 'path/to/baz'
----------------------------------------------------------------------
Ran 136 tests in 0.325s
FAILED (failures=1, skipped=5)
Run Code Online (Sandbox Code Playgroud)
这似乎是因为BAZ_PATH实际上并不存在。不过,我希望这会没问题,因为正在修补。
当在映射字典中 时,"baz": os.environ.get("BAZ_PATH")我替换了BAZ_PATH环境中实际存在的变量,即HOME,它返回 的实际值HOME而不是DUMMY_BAZ_PATH,这使我认为我肯定做了一些错误的修补
AssertionError: '/Users/cestla' != 'path/to/baz'
Run Code Online (Sandbox Code Playgroud)
嗯,显然,我期待着test_controlled_baz顺利通过。
小智 5
所以问题是您将 map 添加为静态变量。您的补丁工作正常,如下所示:
问题是,当它运行时已经太晚了,因为地图变量已经计算出来(在补丁之前)。如果您愿意,可以将其移至init函数,它将正常运行:
class WorkingDirectory:
def __init__(self, env: str):
self.map = {
"foo": "path/to/foo",
"bar": "path/to/bar",
"baz": os.environ.get("BAZ_PATH")
}
self.env = env
self.path = self.map[self.env]
Run Code Online (Sandbox Code Playgroud)
如果由于某种原因你希望保持它静态,你还必须修补对象本身。写这样的东西就可以解决问题:
class TestWorkingDirectory(unittest.TestCase):
@mock.patch.dict(os.environ, {"BAZ_PATH": DUMMY_BAZ_PATH})
def test_controlled_baz(self):
with mock.patch.object(WorkingDirectory, "map", {
"foo": "path/to/foo",
"bar": "path/to/bar",
"baz": os.environ.get("BAZ_PATH")
}):
wd = WorkingDirectory("baz")
self.assertEqual(wd.path, DUMMY_BAZ_PATH)
Run Code Online (Sandbox Code Playgroud)