Tuesday, 25 April 2017

express-cassandra does not work in npm test

I am a noob in node js and express-cassandra

I have a very simple helloworld app written according to the getting started guides of express js and express-cassandra

The app is built by express 4.15.2, chai 3.5.0 and express-cassandra 1.8.0

express-cassandra works fine during the development and it can load my models successfully and it does CRUD stuff pretty well.

But in my unit test it seems that express-cassandra does not load the models although it seems to get the models directory correctly.

app.js

'use strict';

var express = require('express')
var app = express()
var bodyParser = require('body-parser');
var config = require('./config')
var logger = require('./utils/logger') 

const port = config.get('port') 

app.use(bodyParser.json())

app.use('/', require('./routes/helloworld'))
app.use('/', require('./routes/person'))

const server = app.listen(port, function () {
  logger.info(`attend server listening on port ${port}`)
})

module.exports = server

cassandra.js 'use strict';

var config = require('../config')
var logger = require('../utils/logger')
var host = config.get('cassandra_host')
var port = config.get('cassandra_port')
var keyspace = config.get('cassandra_keyspace')
var replStrategy = config.get('cassandra_replication_strategy')
var replFactor = config.get('cassandra_replication_factor')

var models = require('express-cassandra');
models.setDirectory( __dirname + '/models').bind(
    {
        clientOptions: {
            contactPoints: [host],
            protocolOptions: { port: port },
            keyspace: keyspace,
            queryOptions: {consistency: models.consistencies.one}
        },
        ormOptions: {            
            defaultReplicationStrategy : {
                class: replStrategy,
                replication_factor: replFactor
            }, 
            migration: 'safe',
            createKeyspace: true
        }
    },
    function(err) {
        if (err) {
          logger.error(err.message);
        }        
    }
);

module.exports = models;

PersonModel.js

module.exports = {
  fields: {
    id: {
      type: "uuid",
      default: {"$db_function": "uuid()"}
    },
    name: {
      type: "text"
    }
  },

  key: [["id"]],

}

person.js // the route file

// Initialize express & router
var express = require('express')
var logger = require('../utils/logger')
var models = require('../database/cassandra')

var router = express.Router()


router.get('/person', function (req, res) {
  logger.debug('route: ' + req.path + ' ' + req.method)
  logger.debug(req.query)
  console.log(models)

  models.instance.Person.find({}, function (err, people) {
    if (err) {
      logger.error(err)
      res.sendStatus(500)
    } else {
      res.send(people)
    }
  });
})

module.exports = router

and finally the unit test test.js

let chai = require('chai');
let chai_http = require('chai-http');
let should = chai.should();

chai.use(chai_http);

describe('hello world tests', function () {

  var server;

  beforeEach(function () {
    // Delete the cached reference to previous instances of required app
    // This ensures every test has a fresh instance of the app to work with
    // Set log_level=info in test.json to see the server starting for each test case
    delete require.cache[require.resolve('../app/app.js')]
    server = require('../app/app.js');
  });

  afterEach(function (done) {
    server.close(done);
  });

  it('responds to /', function (done) {
    chai.request(server)
        .get('/')
        .end(function(err, res) {
            res.should.have.status(200);
            done();
        });
  });

  it('responds to /person', function (done) {
    chai.request(server)
        .get('/person')
        .end(function(err, res) {
            res.should.have.status(200);
            done();
        });
  });

  it('404 everything else', function (done) {
    chai.request(server)
        .get('/foo')
        .end(function(err, res) {
            res.should.have.status(404);
            done();
        });
  });
});

My test always fail because models.instance.Person is not a constructor. I logged the models during the runtime and during the test:

runtime

[Object],
_properties: [Object],
_set_properties: [Function: f],
_validate: [Function: f],
_get_generic_validator_message: [Function: f],
_format_validator_rule: [Function: f],
_get_validators: [Function: f],
_ask_confirmation: [Function: f],
_ensure_connected: [Function: f],
_execute_definition_query: [Function: f],
_execute_batch: [Function: f],
execute_batch: [Function: f],
get_cql_client: [Function: f],
_create_table: [Function: f],
_create_table_query: [Function: f],
_create_materialized_view_query: [Function: f],
_create_index_query: [Function: f],
_create_custom_index_query: [Function: f],
_get_db_table_schema: [Function: f],
_execute_table_query: [Function: f],
_get_db_value_expression: [Function: f],
_create_where_clause: [Function: f],
_create_find_query: [Function: f],
get_table_name: [Function: f],
is_table_ready: [Function: f],
init: [Function: f],
syncDefinition: [Function: f],
execute_query: [Function: f],
execute_eachRow: [Function: f],
_execute_table_eachRow: [Function: f],
eachRow: [Function: f],
execute_stream: [Function: f],
_execute_table_stream: [Function: f],
stream: [Function: f],
find: [Function: f],
findOne: [Function: f],
update: [Function: f],
delete: [Function: f],
truncate: [Function: f],
drop_mviews: [Function: f],
drop_indexes: [Function: f],
alter_table: [Function: f],
drop_table: [Function: f],
super_Async: [Function: ret],
execute_batchAsync: [Function: ret],
get_cql_clientAsync: [Function: ret],
get_table_nameAsync: [Function: ret],
is_table_readyAsync: [Function: ret],
initAsync: [Function: ret],
syncDefinitionAsync: [Function: ret],
execute_queryAsync: [Function: ret],
execute_eachRowAsync: [Function: ret],
eachRowAsync: [Function: ret],
execute_streamAsync: [Function: ret],
streamAsync: [Function: ret],
findAsync: [Function: ret],
findOneAsync: [Function: ret],
updateAsync: [Function: ret],
deleteAsync: [Function: ret],
truncateAsync: [Function: ret],
drop_mviewsAsync: [Function: ret],
drop_indexesAsync: [Function: ret],
alter_tableAsync: [Function: ret],
drop_tableAsync: [Function: ret],
_ready: true },
nodejs_1     |      Person: 
nodejs_1     |       { [Function: f]
super_: [Object],
_properties: [Object],
_set_properties: [Function: f],
_validate: [Function: f],
_get_generic_validator_message: [Function: f],
_format_validator_rule: [Function: f],
_get_validators: [Function: f],
_ask_confirmation: [Function: f],
_ensure_connected: [Function: f],
_execute_definition_query: [Function: f],
_execute_batch: [Function: f],
execute_batch: [Function: f],
get_cql_client: [Function: f],
_create_table: [Function: f],
_create_table_query: [Function: f],
_create_materialized_view_query: [Function: f],
_create_index_query: [Function: f],
_create_custom_index_query: [Function: f],
_get_db_table_schema: [Function: f],
_execute_table_query: [Function: f],
_get_db_value_expression: [Function: f],
_create_where_clause: [Function: f],
_create_find_query: [Function: f],
get_table_name: [Function: f],
is_table_ready: [Function: f],
init: [Function: f],
syncDefinition: [Function: f],
execute_query: [Function: f],
execute_eachRow: [Function: f],
_execute_table_eachRow: [Function: f],
eachRow: [Function: f],
execute_stream: [Function: f],
_execute_table_stream: [Function: f],
stream: [Function: f],
find: [Function: f],
findOne: [Function: f],
update: [Function: f],
delete: [Function: f],
truncate: [Function: f],
drop_mviews: [Function: f],
drop_indexes: [Function: f],
alter_table: [Function: f],
drop_table: [Function: f],
execute_batchAsync: [Function: ret],
get_cql_clientAsync: [Function: ret],
get_table_nameAsync: [Function: ret],
is_table_readyAsync: [Function: ret],
initAsync: [Function: ret],
syncDefinitionAsync: [Function: ret],
execute_queryAsync: [Function: ret],
execute_eachRowAsync: [Function: ret],
eachRowAsync: [Function: ret],
execute_streamAsync: [Function: ret],
streamAsync: [Function: ret],
findAsync: [Function: ret],
findOneAsync: [Function: ret],
updateAsync: [Function: ret],
deleteAsync: [Function: ret],
truncateAsync: [Function: ret],
drop_mviewsAsync: [Function: ret],
drop_indexesAsync: [Function: ret],
alter_tableAsync: [Function: ret],
drop_tableAsync: [Function: ret],
super_Async: [Function: ret],
_ready: true } },
nodejs_1     |   orm: 
nodejs_1     |    { _options: 
nodejs_1     |       { defaultReplicationStrategy: [Object],
migration: 'safe',
createKeyspace: true },
nodejs_1     |      _models: { event: [Object], person: [Object] },
nodejs_1     |      _keyspace: 'attend_dev',
nodejs_1     |      _connection: 
nodejs_1     |       { contactPoints: [Object],
protocolOptions: [Object],
keyspace: 'attend_dev',
queryOptions: [Object] },
nodejs_1     |      _client: 
nodejs_1     |       Client {
_defaultProfileRetryPolicy: null,
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: 0,
options: [Object],
connected: true,
isShuttingDown: false,
keyspace: 'attend_dev',
metadata: [Object],
hosts: [Object],
_graphOptions: [Object],
_graphSONReader: [Object],
logEmitter: [Function: bound emit],
connecting: false },
nodejs_1     |      _define_connection: 
nodejs_1     |       Client {
_defaultProfileRetryPolicy: null,
domain: null,
_events: {},
_eventsCount: 0,
_maxListeners: 0,
options: [Object],
connected: false,
isShuttingDown: false,
keyspace: 'attend_dev',
metadata: [Object],
hosts: null,
_graphOptions: [Object],
_graphSONReader: [Object] } } }

test

{ [Function: f]
  createClient: [Function],
  setDirectory: [Function],
  bind: [Function],
  bindAsync: [Function: ret],
  uuid: [Function],
  uuidFromString: [Function],
  uuidFromBuffer: [Function],
  timeuuid: [Function],
  timeuuidFromDate: [Function],
  timeuuidFromString: [Function],
  timeuuidFromBuffer: [Function],
  maxTimeuuid: [Function],
  minTimeuuid: [Function],
  doBatch: [Function: f],
  doBatchAsync: [Function: ret],
  _translateFileNameToModelName: [Function],
  directory: '/app/app/database/models',
  modelInstance: {},
  orm: 
   { _options: 
      { defaultReplicationStrategy: [Object],
        migration: 'safe',
        createKeyspace: true },
     _models: {},
     _keyspace: 'attend_test',
     _connection: 
      { contactPoints: [Object],
        protocolOptions: [Object],
        keyspace: 'attend_test',
        queryOptions: [Object] },
     _client: null } }

As you can see the directory is the same but modelInstance array is empty during the test.



via ehsun7b

No comments:

Post a Comment