Como enviar solicitações com JSONs em testes de unidade

96

Eu tenho o código em um aplicativo Flask que usa JSONs na solicitação e posso obter o objeto JSON assim:

Request = request.get_json()

Isso tem funcionado bem, mas estou tentando criar testes de unidade usando o módulo de teste de unidade do Python e estou tendo dificuldade em encontrar uma maneira de enviar um JSON com a solicitação.

response=self.app.post('/test_function', 
                       data=json.dumps(dict(foo = 'bar')))

Isso me dá:

>>> request.get_data()
'{"foo": "bar"}'
>>> request.get_json()
None

O Flask parece ter um argumento JSON onde você pode definir json = dict (foo = 'bar') dentro da solicitação de postagem, mas não sei como fazer isso com o módulo unittest.

Sepehr Nazari
fonte
O que request.datacontém? Freqüentemente, quando a análise json falha devido a uma entrada errada, ela falha silenciosamente e retorna, Noneportanto, os dados de entrada brutos podem não ser json.
Benoît Latinier
>>> request.get_data () '{"foo": "bar"}' >>> request.get_json () Nenhum Não tenho certeza de como a solicitação do flask funciona, mas parece separar data e json, e eu não consigo descobrir como enviar informações ao json em vez dos dados, se isso faz algum sentido.
Sepehr Nazari,
9
Acho que são os cabeçalhos de tipo de conteúdo, tente configurá-los como appliacation / json. também o parâmetro force é útil, mas você provavelmente não quer ir lá apenas para fazer os testes de unidade passarem, melhor mudar o mime
user3012759

Respostas:

194

Alterando a postagem para

response=self.app.post('/test_function', 
                       data=json.dumps(dict(foo='bar')),
                       content_type='application/json')

consertou.

Agradecimentos ao user3012759.

Sepehr Nazari
fonte
estava destruindo minha cabeça com isso. Não entendo por que você tem que descartar os dados quando já está especificando o application/jsontipo de conteúdo.
dimmg
Acredito que seja porque tudo que você envia em uma postagem tem que ser uma string.
Sepehr Nazari
17
É incrível que isso não esteja nos documentos, porque o test_client do flask não tem documentos de API!
rjurney,
Como obter dados da resposta?
variável
@variable, com uma resposta de uma post solicitação como se resp = client.post('/my/endpoint/',json=my_json_data)você pudesse acessar os dados como bytes com resp.data.
amiabl
44

ATUALIZAÇÃO: Como os flask.testing.FlaskClientmétodos liberados do Flask 1.0 aceitam jsonargumentos e Response.get_jsonmétodos adicionados, consulte o exemplo .

para Flask 0.x você pode usar o recibo abaixo:

from flask import Flask, Response as BaseResponse, json
from flask.testing import FlaskClient
from werkzeug.utils import cached_property


class Response(BaseResponse):
    @cached_property
    def json(self):
        return json.loads(self.data)


class TestClient(FlaskClient):
    def open(self, *args, **kwargs):
        if 'json' in kwargs:
            kwargs['data'] = json.dumps(kwargs.pop('json'))
            kwargs['content_type'] = 'application/json'
        return super(TestClient, self).open(*args, **kwargs)


app = Flask(__name__)
app.response_class = Response
app.test_client_class = TestClient
app.testing = True
Victor Gavro
fonte
1
E não se esqueça de que o argumento json não deve ser uma dictstring JSON!
LaundroMat