【发布时间】:2018-07-02 14:49:57
【问题描述】:
我正在尝试进行单元测试,以验证从 JSON 编码文件中读取凭据的函数。由于凭据本身不是固定的,单元测试需要提供一些,然后测试它们是否被正确检索。
这里是凭证功能:
def read_credentials():
basedir = os.path.dirname(__file__)
with open(os.path.join(basedir, "authentication.json")) as f:
data = json.load(f)
return data["bot_name"], data["bot_password"]
这是测试:
def test_credentials(self):
with patch("builtins.open", mock_open(
read_data='{"bot_name": "name", "bot_password": "password"}\n'
)):
name, password = shared.read_credentials()
self.assertEqual(name, "name")
self.assertEqual(password, "password")
但是,当我运行测试时,json 代码会因解码错误而崩溃。查看 json 代码本身,我很难理解为什么模拟测试会失败,因为 json.load(f) 只是调用 f.read() 然后调用 json.loads()。
确实,如果我将身份验证功能更改为以下内容,则单元测试有效:
def read_credentials():
# Read the authentication file from the current directory and create a
# HTTPBasicAuth object that can then be used for future calls.
basedir = os.path.dirname(__file__)
with open(os.path.join(basedir, "authentication.json")) as f:
content = f.read()
data = json.loads(content)
return data["bot_name"], data["bot_password"]
我不一定介意以这种形式保留我的代码,但我想了解我的测试中是否有什么错误可以使我的函数保持其原始形式。
堆栈跟踪:
Traceback (most recent call last):
File "test_shared.py", line 56, in test_credentials
shared.read_credentials()
File "shared.py", line 60, in read_credentials
data = json.loads(content)
File "/home/philip/.local/share/virtualenvs/atlassian-webhook-basic-3gOncDp4/lib/python3.6/site-packages/flask/json/__init__.py", line 205, in loads
return _json.loads(s, **kwargs)
File "/usr/lib/python3.6/json/__init__.py", line 367, in loads
return cls(**kw).decode(s)
File "/usr/lib/python3.6/json/decoder.py", line 339, in decode
obj, end = self.raw_decode(s, idx=_w(s, 0).end())
File "/usr/lib/python3.6/json/decoder.py", line 357, in raw_decode
raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)
【问题讨论】:
-
您的
shared.read_credentials()是做什么的?它似乎根本没有使用read_data。请向我们展示您的堆栈跟踪。 -
@blhsing read_credentials() 将从 JSON 文件中检索到的值返回给调用者。
-
是的,但我没有看到
read_data传递给它。 -
我的理解是 read_data 告诉 mock 在打开文件上调用 read() 时要提供什么。正如我在原帖中所说,如果我分离出对 read() 的调用,但如果我让 json 直接进行读取则不行。
-
我明白了。你确实是对的。我读得不够仔细。我刚刚测试了你所谓的错误代码,它在我的环境中工作。我也没有看到加载 json 的两种方式有什么不同,因为
json.load确实只是在传递给它的文件对象上调用read()。我认为它必须是你环境中的其他东西。
标签: json python-3.x mocking