Как использовать mock_open с json.load ()? - PullRequest
0 голосов
/ 02 июля 2018

Я пытаюсь заставить работать модульный тест, который проверяет функцию, которая считывает учетные данные из файла в кодировке 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)

1 Ответ

0 голосов
/ 25 августа 2018

У меня возникла та же проблема, и я обошел ее, издеваясь над json.load и builtins.open:

import json
from unittest.mock import patch, MagicMock

# I don't care about the actual open
p1 = patch( "builtins.open", MagicMock() )

m = MagicMock( side_effect = [ { "foo": "bar" } ] )
p2 = patch( "json.load", m )

with p1 as p_open:
    with p2 as p_json_load:
        f = open( "filename" )
        print( json.load( f ) ) 

Результат:

{'foo': 'bar'}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...