Тестирование колб, почтовый файл и вложенные словари - PullRequest
0 голосов
/ 22 сентября 2018

Я создал приложение Flask и хотел его протестировать.В одной конечной точке я хотел бы опубликовать составной запрос, который включает в себя файл и сложный объект JSON.Сначала я подумал об использовании werkzeug EnvironBuilder для этой задачи, поскольку он, кажется, обеспечивает достаточно автоматизированный подход, обработку типов содержимого и т. Д. Мой фрагмент кода для подготовки запроса следующий:

# client is an instance of FlaskClient produced using a pytest fixture and the method test client

def _post(endpoint, file_path=None, serialized_message=None):
        with open(file_path, 'rb') as fin:
                fil = io.BytesIO(fin.read())
        file_name = file_path.split(os.sep)[-1]
        builder = EnvironBuilder(path='/' + endpoint,
                                 method='POST',
                                  data=json.loads(
                                      serialized_message),
                                content_type="application/json")
        builder.files[file_name] = fil
        result = client.open(builder, buffered=True)
        return result

Thisошибка со следующей ошибкой:

 def _add_file_from_data(self, key, value):
        """Called in the EnvironBuilder to add files from the data dict."""
        if isinstance(value, tuple):
            self.files.add_file(key, *value)
        elif isinstance(value, dict):
            from warnings import warn
            warn(DeprecationWarning('it\'s no longer possible to pass dicts '
                                    'as `data`.  Use tuples or FileStorage '
                                    'objects instead'), stacklevel=2)
            value = dict(value)
            mimetype = value.pop('mimetype', None)
            if mimetype is not None:
                value['content_type'] = mimetype
>           self.files.add_file(key, **value)
E           TypeError: add_file() got an unexpected keyword argument 'globalServiceOptionId'

С globalServiceOptionId, являющимся ключом вложенного словаря в словаре, который я публикую.У меня есть некоторые мысли по поводу обхода этой проблемы с преобразованием в строковые jsons внутренних словарей, но я хотел бы получить что-то более конкретное в качестве ответа, так как я не хочу, чтобы представление запроса изменялось внутри и снаружи тестирования.Спасибо.

Обновление 1

Форма словаря с паролем не имеет большого значения, если в нем есть словари.Этот json приведен в следующем примере:

{
    "attachments": [],
    "Ids": [],
    "globalServiceOptions": [{
      "globalServiceOptionId": {
        "id": 2,
        "agentServiceId": {
          "id": 2
        },
        "serviceOptionName": "Time",
        "value": "T_last",
        "required": false,
        "defaultValue": "T_last",
        "description": "UTC Timestamp",
        "serviceOptionType": "TIME"
      },
      "name": "Time",
      "value": null
    }]
  }

Обновление 2

Я проверил другой фрагмент:

    def _post(endpoint, file_path=None, serialized_message=None):
        with open(file_path, 'rb') as fin:
                fil = io.BytesIO(fin.read())
        files = {
         'file': (file_path, fil, 'application/octet-stream')
        }
        for key, item in json.loads(serialized_message).items():
            files[key] = (None, json.dumps(item), 'application/json')

        builder = EnvironBuilder(path='/' + endpoint,
                                 method='POST', data=files,
                                 )
        result = client.open(builder, buffered=True)
        return result

Хотя это работает без ошибок, Flask распознает (как и ожидалось)) входящие jsons в виде файлов, что опять-таки требует другой обработки во время тестирования и нормальной работы.

1 Ответ

0 голосов
/ 16 января 2019

Я столкнулся с подобной проблемой, и в итоге мне удалось изменить подход к данным, чтобы исключить вложенные разногласия.Используя ваш пример JSON, выполнение следующего должно позволить ему очистить EnvironBuilder:

data_json = {
    "attachments": [],
    "Ids": [],
    "globalServiceOptions": [json.dumps({  # Dump all nested JSON to a string representation
            "globalServiceOptionId": {
                "id": 2,
                "agentServiceId": {
                    "id": 2
                },
                "serviceOptionName": "Time",
                "value": "T_last",
                "required": false,
                "defaultValue": "T_last",
                "description": "UTC Timestamp",
                "serviceOptionType": "TIME"
            },
            "name": "Time",
            "value": null
        })
    ]
}
builder = EnvironBuilder(path='/' + endpoint,
                             method='POST',
                              data=data_json,
                            content_type="application/json")

При использовании вышеизложенного подхода все еще разрешается надлежащим образом передавать вложенный dict / JSON при очистке ограничения werkzeug.

...