Solucionado (ver solução)
Solucionado
(ver solução)
7
respostas

Dúvida sobre teste de produtos inválidos

Boa tarde. Estou com uma dúvida neste exercício. Eu segui o passo-a-passo dele até aqui e quando faço o teste de produtos válidos ele envia uma mensagem de ok e cadastra o produto no banco de dados. Porém, na hora do teste de produtos inválidos, aparece a mensagem:

1) #ProdutosController #cadastro de novo produto com dados invalidos:
     Error: expected 400 "Bad Request", got 200 "OK"
      at Test._assertStatus (node_modules/supertest/lib/test.js:266:12)
      at Test._assertFunction (node_modules/supertest/lib/test.js:281:11)
      at Test.assert (node_modules/supertest/lib/test.js:171:18)
      at Server.assert (node_modules/supertest/lib/test.js:131:12)
      at emitCloseNT (net.js:1537:8)

No entanto, o produto inválido não é cadastrado no banco, o que é o correto. A mensagem que ele deveria retornar neste caso não seria o erro 400? No entanto, a impressão que eu tenho é que ele retorna 200.

Este é o meu código de cadastro de produtos: produtos.js (app routes)

module. exports = function(app) {
    app.get("/produtos", function(req, res) {

        var connection = app.infra.connectionFactory();
        var produtosDAO = new app.infra.ProdutosDAO(connection);

        produtosDAO.lista(function(erros,resultados){
            //res.render('produtos/lista', {lista:resultados});
            res.format({
                html: function(){
                    res.render('produtos/lista',{lista:resultados});
                },
                json: function(){
                    res.json(resultados)
                }
            });
        });
        connection.end();
    });

    app.get("/produtos/form", function(req, res){
        res.render('produtos/form', 
            {errosValidacao:{}, produto: {}});
    });

    app.post("/produtos", function(req, res) {

        var produto = req.body;
        console.log(produto);

        req.assert('titulo','Titulo é obrigatório').notEmpty();
        req.assert('descricao','Descrição é obrigatória').notEmpty();
        req.assert('preco','Formato inválido').isFloat()

        var erros = req.validationErrors();

        if(erros){
            //res.render('produtos/form', {errosValidacao:erros, produto:produto});
            res.format({
                html: function(){
                res.render('produtos/form',{errosValidacao:erros,produto:produto});
            },
                json: function(){
                    res.status(400).json(erros);
                }
            });
            return;
        }

        var connection = app.infra.connectionFactory();
        var produtosDAO = new app.infra.ProdutosDAO(connection);

        produtosDAO.salva(produto,function(erros,resultados){
            //res.render('produtos/lista');
            console.log(erros)
            res.redirect('/produtos');
        });
        connection.end();
    });
}

produtos.js (test)

var express = require('../config/express')();
var request = require('supertest')(express);

describe('#ProdutosController', function(){
    it('listagem json', function(done){
        //console.log("Teste de verificação de listagem de json");
        /*var configuracoes = {
            hostname: 'localhost',
            port:3000,
            path: '/produtos',
            headers: {
                'Accept':'application/json'
            }
        };
        http.get(configuracoes,function(res){
            assert.equal(res.statusCode, 200);
            assert.equal(res.headers['content-type'],'application/json; charset=utf-8');
            done();
        });*/
        request.get('/produtos')
        .set('Accept','application/json')
        .expect('Content-Type',/json/)
        .expect(200,done);
    });

    it('#cadastro de novo produto com dados invalidos',function(done){
        request.post('/produtos')
        .send({titulo:"",descricao:"novo livro"})
        .expect(400,done);
    });

    it('#cadastro de novo produto com dados validos',function(done){
        request.post('/produtos')
        .send({titulo:"titulo",descricao:"novo livro",preco:200})
        .expect(302,done);
    });
});
7 respostas

Oi Cássia, tudo bem? Acho que é por que você precisa o usar o set do content-type ou Accept como json por que dessa forma, acredito que ele esteja enviando a resposta como HTML e ai, dentro da resposta do HTML você não está configurando o status 400 do HTTP.

Cássia, em caso de erros, ao renderizar a view você se esqueceu de enviar o status 400 (assim como fez enviando a resposta em JSON).

if (erros) {
    //res.render('produtos/form', {errosValidacao:erros, produto:produto});
    res.format({
        html: function() {
            // AQUI DEVERIA SER
            res.status(400).render('produtos/form', { errosValidacao: erros, produto: produto });
            // INCORRETO res.render('produtos/form',errosValidacao:erros,produto:produto});
        },
        json: function() {
            res.status(400).json(erros);
        }
    });
    return;
}

Boa noite. Então, eu corrigi e agora deu isso:

cassia@Cassia-PC:~/casadocodigo$ node_modules/mocha/bin/mocha


  #ProdutosController
    ✓ listagem json (262ms)
{ titulo: '', descricao: '' }
    ✓ #cadastro de novo produto com dados invalidos (131ms)
{ titulo: 'titulo', descricao: 'novo livro', preco: 400 }
null
    ✓ #cadastro de novo produto com dados validos (87ms)
3 passing (501ms)

Pessoal, acho que entendi o que está havendo. Na verdade, o retorno esperado nesse trecho:

it('#cadastro de novo produto com dados invalidos',function(done){
        request.post('/produtos')
        .send({titulo:"",descricao:"novo livro"})
        .expect(400,done);
    });

Não é 400, e sim, 302. Pois eu espero que, cadastrando os produtos sem os dados obrigatórios, ele me retorne 302. Mas, como eu cadastrei produto com dado inválido, o sistema me retornou um Bad Request, erro 400. Pelo menos foi assim que entendi. Então, o código correto nesse trecho é:

it('#cadastro de novo produto com dados invalidos',function(done){
        request.post('/produtos')
        .send({titulo:"",descricao:"novo livro"})
        .expect(302,done);
    });
solução!

Cássia, veja bem:

cassia@Cassia-PC:~/casadocodigo$ node_modules/mocha/bin/mocha


  #ProdutosController
    ✓ listagem json (262ms)
{ titulo: '', descricao: '' }
    ✓ #cadastro de novo produto com dados invalidos (131ms)
{ titulo: 'titulo', descricao: 'novo livro', preco: 400 }
null
    ✓ #cadastro de novo produto com dados validos (87ms)
3 passing (501ms)

Os três testes deram ok. Não há erro.

Sobre o teste de cadastro de produto inválido:

it('#cadastro de novo produto com dados invalidos', function(done) {

    // Faça uma requisição para a rota /produtos
    request.post('/produtos')
        // Envie ao servidor um JSON contendo um produto inválido
        .send({ titulo: "", descricao: "novo livro" })

        // Espere que o servidor te responda com o status HTTP 400 (Bad Request)
        .expect(400, done);
});

Status 400:

O código de status de resposta de solicitação incorreta HTTP 400 indica que o servidor não conseguiu entender a solicitação devido a sintaxe inválida. O cliente não deve repetir esta solicitação sem modificação.

Mozilla Developer Network

Pense, você está tentando cadastrar um produto inválido no seu servidor. O que você espera que o servidor te responda?

Sim, ele deve te responder que você fez uma solicitação incorreta (bad request). Neste caso seu código estava correto em .expect(400, done);

Ta, mas por que os objetos em JSON estão aparecendo ali no teste? Tem um null ali também, de onde veio?

Veio do seu código. Veja o arquivo que controla as rotas de produtos.

Logo no começo da configuração da rota de POST para /produtos você está logando o produto:

app.post("/produtos", function(req, res) {

            var produto = req.body;
            console.log(produto);
// Resto do código

O null vem de quando você invoca o método salva no seu produtosDAO.

produtosDAO.salva(produto, function(erros, resultados) {
    //res.render('produtos/lista');
    console.log(erros)
    res.redirect('/produtos');
});

Não há erros, mas você está logando o conteúdo de erros (nulo).

Você poderia considerar utilizar da seguinte maneira:

if (erros) console.error(erros)

Obs: o console.error faz o mesmo que console.log, a diferença é que o primeiro envia para stderr (Standard Error) a saída padrão de erros. O segundo envia para stdout (Standard Output) a saída padrão. Neste caso o resultado visual será o mesmo, você poderia experimentar utilizar ambos no console do navegador, o console.error deixará o conteúdo vermelho.

Mas concluindo, aparentemente seu código está correto.

Isso mesmo, fez sentido pra mim a explicação do Pedro. Seus testes não estão errados Cássia, a não ser que a lógica que você esteja tentando implementar seja outra que a gente não entendeu bem.

Entendi, obrigada aos dois :)