16
respostas

Video 7 - Aula 7 - Banco de dados de testes vazio

Não sei o que pode estar acontecendo, olhei em algumas respostas do fórum e não encontrei a solução.

Criei o banco de testes, mas ele só aparece vazio, onde ele recebe a função de gravar no teste? O nome da tabela de teste deve ser a mesma da produção, pela duvida criei produtos e livros? Não aparece nada no console de erros.

ConnectionFactory

var mysql  = require('mysql');

function createDBConnection(){
    if(!process.env.NODE_ENV){
      return mysql.createConnection({
          host: 'localhost',
          user: 'root',
          password: '',
          database: 'casadocodigo_nodejs'
      });
    }
    if(process.env.NODE_ENV == 'test'){
      return mysql.createConnection({
          host: 'localhost',
          user: 'root',
          password: '',
          database: 'casadocodigo_nodejs_test'
      });
    }
}

module.exports = function() {
    return createDBConnection;
}

produtos.js

module.exports = function(app) {
   var listaProdutos = function(req,res,next){
       var connection = app.infra.connectionFactory();
        var produtosBanco = new app.infra.ProdutosDAO(connection);

        produtosBanco.lista(function(erros, resultados){
          if(erros){
            return next(erros);
          }
             res.format({
                html: function(){
                    res.render("produtos/lista",{lista:resultados});
                },
                json: function(){
                    res.json(resultados);
                }
            });
        });

        connection.end();
   };

    app.get("/produtos", listaProdutos);

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

        req.assert('titulo','Titulo é obrigatório').notEmpty()
        req.assert('preco','Formato inválido').isFloat()

        var erros = req.validationErrors();
        if(erros){
          console.log(erros);
          res.send(erros);
         return;
          res.format({
                 html: function(){
                    res.status(400).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){
            console.log(erros);
            res.redirect('/produtos');
        });
    })
}

produtos.js test

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

describe('ProdutosController', function(){
  it('listagem json', function(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:"node",descricao:"livro node",preco:20.50})
    .expect(302,done());//302 redirect redireciona a página
  });
});
16 respostas

Opa, vc tem um teste que faz inserção no banco.. mas antes realmente precisa criar a tabela lá. O teste que preenche o banco é o de cadastro de novos produtos válidos.

Create table no mysql, até a criação da tabela foi, mas não está gravando na tabela de teste.

Vou alterar a pergunta, o comando de testar no Windows é diferente.

É só utilizar o SET NODE_ENV=test e depois digitar node_modules/mocha/bin/mocha?

Esse pode ser um dos motivos que não está salvando, porque o banco de teste existe, a tabela também.

Agora apareceu esse erro:

TypeError: Cannot read property 'query' of undefined
    at ProdutosDAO.lista (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\app\infra\ProdutosDAO.js:6:21)
    at listaProdutos (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\app\routes\produtos.js:6:23)
    at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\layer.js:95:5)
    at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\route.js:131:1
3)

    at Route.dispatch (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\rout
e.js:112:3)
    at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\expre
ss\lib\router\layer.js:95:5)
    at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:277:22
    at Function.process_params (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\ro
uter\index.js:330:12)
    at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:271:1
0)
    at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express-validator\lib\express_validator
.js:355:5
    at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\expre
ss\lib\router\layer.js:95:5)
    at trim_prefix (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.j
s:312:13)
    at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:280:7
    at Function.process_params (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:330:12)
    at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:271:10)
    at jsonParser (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\body-parser\lib\types\json.js:103:7)

Como eu posso verificar se essa linha está funcionando?

  .send({titulo:"node",descricao:"livro node",preco:20.50})

Esses dados estão sendo enviados para o banco, mas quando eu olho mesmo pelo phpMyadmin está vazio.

Como eu sei que criei o banco e a tabela corretamente e como eu verifico que os dados estão sendo salvos?

Na verdade, se retornou 200 está funcionando.. pq ele está batendo no controller... no código do teste, limpamos o banco no fim de cada teste.. acho que é isso que está acontecendo e ta te dando a sensação que não está inserindo. https://cursos.alura.com.br/course/node-js/task/12883

Estou tendo um problema na mesma aula, mesmo usando o código abaixo, é usado o banco de dev:

var mysql = require('mysql');

var connectMYSQL = function(){
    if(!process.env.NODE_ENV){
        return mysql.createConnection({
                host:'localhost',
                user:'root',
                password:'',
                database:'casadocodigo_nodejs'
        });
    }
    if(!process.env.NODE_ENV == 'test'){
        return mysql.createConnection({
                host:'localhost',
                user:'root',
                password:'',
                database:'casadocodigo_nodejs_test'
        });
    }
};

module.exports = function(){
    return connectMYSQL;
}

Pode ser isso, vou passar para próxima lição, mas vou deixar o tópico aberto por causa da outra dúvida do Samuel.

Eu não sei explicar o que pode ser, mas tem algo no funcionamento do node que eu ainda não entendi, porque eu aprendi backend com PHP e por mais que apareça um erro, eu sei onde é o erro, o mesmo não acontece com o node, estou tendo dificuldades em encontrar os erros.

O problema está na variável de ambiente.

A mensagem de erro que foi postada diz o seguinte:

TypeError: Cannot read property 'query' of undefined

Essa propriedade "query" faz parte da propriedade "_connection", que é criada ao contruir o seu ProdutosDAO.

Por sua vez, a ProdutosDAO recebe essa conexão a partir da rota que faz a requisição. Por exemplo:

 app.get('/produtos', function(req,res, next){
        var connection = app.infra.connectionFactory();
        var produtosDAO  = new app.infra.ProdutosDAO(connection);

        //Resto do código omitido
    });

O erro vem da ConnectionFactory. Ela não está retornando nada, por isso não funcionam as consultas.

A ConnectionFactory retorna vazia por causa que não entrou em nenhum dos IFs. Repetindo o código postado acima, com pequenos ajustes meus para testes:

var mysql = require('mysql');

var connectMYSQL = function(){

    //Novo! Teste para ver o tipo de conexao!
    console.log('tipo de conexao:' + process.env.NODE_ENV);

    if(!process.env.NODE_ENV){
        //Teste!
        console.log('A variavel de ambiente nao existe!');

        return mysql.createConnection({
                host:'localhost',
                user:'root',
                password:'',
                database:'casadocodigo_nodejs'
        });
    }
    if(!process.env.NODE_ENV == 'test'){
        //Teste!
        console.log('A variavel de ambiente existe mas nao chama test!');
        return mysql.createConnection({
                host:'localhost',
                user:'root',
                password:'',
                database:'casadocodigo_nodejs_test'
        });
    }
};

module.exports = function(){
    return connectMYSQL;
}

Se existir uma variável de ambiente definida com qualquer nome, a ConnectionFactory vai retornar vazia, já que ela somente retorna conexão se a variável não existir, ou se ela existir e não chamar test.

Se vocês testarem e tentarem abrir uma rota que consome a conexão, devem estar vendo no terminal apenas a mensagem "tipo de conexao...."

Para listar as variáveis de ambientes existentes no Windows, dentro do terminal, basta digitar o comando SET. Para definir, basta fazer algo assim:

SET NODE_ENV=nome_da_variavel

Uma outra forma de definir a variável de ambiente (não recomendada) seria fazer via código dentro do Node. Isso poderia ser feito dentro do seu arquivo "express.js". Exemplo:

var express = require('express');
var load = require('express-load');
var bodyParser = require('body-parser');
var expressValidator = require('express-validator');

module.exports = function() {

    var app = express();
    //PARA DEFINIR O TIPO DE AMBIENTE
    //NAO SE RECOMENDA FAZER ISSO DENTRO DO CODIGO
    process.env.NODE_ENV = 'test';

    //Resto do código omitido

}

É importante lembrar que precisa testar as conexões com o banco fora do Node, ou seja, se o nome do servidor e do banco estão corretos, e se as tabelas dos bancos de testes e de produção tem a mesma estrutura. Se a comunicação com ambos está OK, então tem que definir essa variável de ambiente.

Oi Daniel, não tinha visto a sua resposta, obrigada. Eu fiquei um tempo sem mexer, agora preciso lembrar o que eu estava fazendo vou olhar esses códigos que você colocou, então o erro deve ser na connectioFactory?

Esse erro começou só na parte de testes, porque antes estava funcionando.

Meu código está um pouco diferente do seu, não sei se as linhas do teste estão no lugar correto, erro app crashed:

ProdutosDAO.js

function ProdutosDAO(connection){
    this._connection = connection;
}

 ProdutosDAO.prototype.lista = function(callback){
    this._connection.query('select * from livros', callback);
}

ProdutosDAO.prototype.salva = function(produto, callback){
    this._connection.query('insert into livros set ?', produto, callback);
}

module.exports = function(){
   return ProdutosDAO;
}

ConnectionFactory

var mysql  = require('mysql');

function createDBConnection(){

  //Novo! Teste para ver o tipo de conexao!
  console.log('tipo de conexao:' + process.env.NODE_ENV);

  if(!process.env.NODE_ENV){
      //Teste!
      console.log('A variavel de ambiente nao existe!');

  if (!process.env.NODE_ENV || process.env.node === 'dev') {
      return mysql.createConnection({
          host: 'localhost',
          user: 'root',
          password: '',
          database: 'casadocodigo_nodejs'
      });
  }

  if (process.env.NODE_ENV == 'test') {
      return mysql.createConnection({
          host: 'localhost',
          user: 'root',
          password: '',
          database: 'casadocodigo_nodejs_test'
      });
  }

}

module.exports = function() {
    return createDBConnection;
}

express.js

var express = require('express');
var load = require('express-load');
var bodyParser = require('body-parser');
var expressValidator = require('express-validator');

module.exports = function() {
    var app = express();
    app.set('view engine', 'ejs');
    app.set('views','./app/views');

    app.use(bodyParser.urlencoded({extended: true}));
    app.use(bodyParser.json());
    app.use(expressValidator());

    //req -> middlewareBodyParsers
    load('routes',{cwd: 'app'})
    .then('infra')
    .into(app);
    return app;
}

Agora aparece no navegador:

Internal Server Error

E aponta erro de GET na página produtos:

Já me perdi no que eu tava fazendo, no curso tem muitas alterações nessas conexões e posso ter perdido algo no meio dessas mudanças:

module.exports = function(app) {
   var listaProdutos = function(req,res,next){
       var connection = app.infra.connectionFactory();
        var produtosBanco = new app.infra.ProdutosDAO(connection);

        produtosBanco.lista(function(erros, resultados,next){
          if(erros){
            return next(erros);
          }
             res.format({
                html: function(){
                    res.render("produtos/lista",{lista:resultados});
                },
                json: function(){
                    res.json(resultados);
                }
            });
        });

        connection.end();
   };

    app.get("/produtos", listaProdutos);

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

        req.assert('titulo','Titulo é obrigatório').notEmpty()
        req.assert('preco','Formato inválido').isFloat()

        var erros = req.validationErrors();
        if(erros){
          console.log(erros);
          res.send(erros);
         return;
          res.format({
                 html: function(){
                    res.status(400).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){
            console.log(erros);
            res.redirect('/produtos');
        });
    })
}

Talvez tenha que rever as aulas todas... :(

Retornou conexão undefined e que a variável de ambiente não existe, depois carregou a página, não entendi...

Coloquei SET NODE_ENV=dev

Ele dá o erro novamente, não entendi, o que está acontecendo com a conexão?

TypeError: Cannot read property 'query' of undefined
   at ProdutosDAO.lista (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\app\infra\ProdutosDAO.js:6:21)
   at listaProdutos (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\app\routes\produtos.js:6:23)
   at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\layer.js:95:5)
   at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\route.js:131:13)
   at Route.dispatch (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\route.js:112:3)
   at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\layer.js:95:5)
   at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:277:22
   at Function.process_params (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:330:12)
   at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:271:10)
   at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express-validator\lib\express_validator.js:355:5
   at Layer.handle [as handle_request] (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\layer.js:95:5)
   at trim_prefix (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:312:13)
   at C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:280:7
   at Function.process_params (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:330:12)
   at next (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\express\lib\router\index.js:271:10)
   at jsonParser (C:\Users\Gisele\Documents\Alura\Node\casadocodigo\node_modules\body-parser\lib\types\json.js:103:7)

Percebi uma coisa, eu estava seguindo os vídeos, não sei se teve alguma alteração, mas você falou que o problema é a connection, olhando no geral, eu percebi que a variável connection foi criada duas vezes no meu código.

Copiei algo errado, dupliquei código?

Desculpa, mas eu não consegui entender muito bem essa parte de criação da conexão com prototype e o código fica dividido em 3 arquivos...

Arquivo app/routes/produtos.js

var listaProdutos = function(req,res,next){
       var connection = app.infra.connectionFactory();
        var produtosBanco = new app.infra.ProdutosDAO(connection);
  //Resto do código omitido
  //Resto do código omitido
  var connection = app.infra.connectionFactory();
        var produtosDAO = new app.infra.ProdutosDAO(connection);
        produtosDAO.salva(produto, function(erros, resultados){
            console.log(erros);
            res.redirect('/produtos');
        });

Completo:

module.exports = function(app) {
   var listaProdutos = function(req,res,next){
       var connection = app.infra.connectionFactory();
        var produtosBanco = new app.infra.ProdutosDAO(connection);

        produtosBanco.lista(function(erros, resultados,next){
          console.log(erros);
          if(erros){
            return next(erros);
          }
             res.format({
                html: function(){
                    res.render("produtos/lista",{lista:resultados});
                },
                json: function(){

                    res.json(resultados);
                }
            });
        });

        connection.end();
   };

    app.get("/produtos", listaProdutos);

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

        req.assert('titulo','Titulo é obrigatório').notEmpty()
        req.assert('preco','Formato inválido').isFloat()

        var erros = req.validationErrors();
        if(erros){
          console.log(erros);
          res.send(erros);
         return;
          res.format({
                 html: function(){
                    res.status(400).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){
            console.log(erros);
            res.redirect('/produtos');
        });
    })
}

Deu um erro estranho, pior que eu não mexi muito no código. Eu não consigo enxergar o erro, tirei tudo e funciona sem essa parte da variável, não sei porque.

Sem erro:

var mysql  = require('mysql');

function createDBConnection(){
    return mysql.createConnection({
        host: 'localhost',
        user: 'root',
        password: '',
        database: 'casadocodigo_nodejs'
    });
}

module.exports = function() {
    return createDBConnection;
}

Com a alteração da variável agora aparece unexpected token )

var mysql  = require('mysql');

function createDBConnection(){

  //Novo! Teste para ver o tipo de conexao!
  console.log('tipo de conexao:' + process.env.NODE_ENV);

  if(!process.env.NODE_ENV){
      //Teste!
      console.log('A variavel de ambiente nao existe!');

  if (!process.env.NODE_ENV || process.env.node === 'dev') {
      return mysql.createConnection({
          host: 'localhost',
          user: 'root',
          password: '',
          database: 'casadocodigo_nodejs'
      });
  }

  if (process.env.NODE_ENV == 'test') {
      return mysql.createConnection({
          host: 'localhost',
          user: 'root',
          password: '',
          database: 'casadocodigo_nodejs_test'
      });
  }
}

module.exports = function() {
    return createDBConnection;
}

De acordo com o seu último teste, o erro não ocorre se a sua função de "createDBConnection" não tiver nenhum "if". Ou seja, como o arquivo tem apenas uma conexão, sempre vai ocorrer o "return" dela para o resto de sua aplicação.

Quando não existe um retorno, ou seja, o retorno é nulo, ocorrem essas mensagens de erro de:

TypeError: Cannot read property 'query' of undefined

Essa propriedade "query" somente vai existir se uma conexão for criada.

Nesse último arquivo de conexão (onde aparece a mensagem de erro de "unexpected token"), você pode fazer o seguinte ajuste para identificar melhor o problema:

var mysql  = require('mysql');

function createDBConnection(){

  //Novo! Teste para ver o tipo de conexao!
  console.log('tipo de conexao:' + process.env.NODE_ENV);

  if(!process.env.NODE_ENV){
      //Teste!
      console.log('A variavel de ambiente nao existe!');
  }

    if (!process.env.NODE_ENV || process.env.node == 'dev') {
      console.log('Conexao 1 - A variavel de ambiente nao existe ou chama dev!');
      return mysql.createConnection({
          host: 'localhost',
          user: 'root',
          password: '',
          database: 'casadocodigo_nodejs'
      });
    }

  if (process.env.NODE_ENV == 'test') {
       console.log('Conexao 2 - A variavel de ambiente existe e chama test!');
      return mysql.createConnection({
          host: 'localhost',
          user: 'root',
          password: '',
          database: 'casadocodigo_nodejs_test'
      });
  }
}

module.exports = function() {
    return createDBConnection;
}

Esses erros de "unexpected token" podem ocorrer quando tem alguma estrutura de código que não fechou corretamente, por exemplo uma função ou um if.

Um link que ajuda a identificar erros em arquivos Javascript é este:

http://www.jshint.com/

Obrigada. Mesmo erro da query, porque não cria a conexão dev? Ah, não aparece nada de mensagem sobre a variável.

Porque algumas mensagens de erro aparecem no prompt e outras no navegador?

Dos ifs, eu não entendi direito onde fechava cada if, mas não tinha nenhum ) a mais.

Quando o servidor está rodando ele fica aprecendo null depois de um tempo, sem o seu código.