node.js unit-testing bookshelf.js knex.js

node.js - Pruebas unitarias con Bookshelf.js y knex.js



unit-testing (2)

Soy relativamente nuevo en Node y estoy trabajando en un proyecto usando knex y bookshelf. Estoy teniendo un poco de problemas en la unidad probando mi código y no estoy seguro de lo que estoy haciendo mal.

Básicamente tengo un modelo (llamado VorcuProduct) que se ve así:

var VorcuProduct = bs.Model.extend({ tableName: ''vorcu_products'' }); module.exports.VorcuProduct = VorcuProduct

Y una función que guarda un VorcuProduct si no existe en la base de datos. Bastante sencillo. La función que hace esto se ve así:

function subscribeToUpdates(productInformation, callback) { model.VorcuProduct .where({product_id: productInformation.product_id, store_id: productInformation.store_id}) .fetch() .then(function(existing_model) { if (existing_model == undefined) { new model.VorcuProduct(productInformation) .save() .then(function(new_model) { callback(null, new_model)}) .catch(callback); } else { callback(null, existing_model) } }) }

¿Cuál es la forma correcta de probar esto sin golpear el DB? ¿Debo simular la fetch para devolver un modelo o undefined (según la prueba) y luego hacer lo mismo con save ? ¿Debo usar rewire para esto?

Como pueden ver, estoy un poco perdido, por lo que cualquier ayuda será apreciada.

¡Gracias!


Esta es en realidad una gran pregunta que presenta tanto el valor como las limitaciones de las pruebas unitarias.

En este caso particular, la lógica no tachada es bastante simple: solo un bloque if , por lo que es discutible si vale la pena el esfuerzo de prueba de la unidad, por lo que la respuesta aceptada es buena y señala el valor de la integración a pequeña escala pruebas.

Por otro lado, el ejercicio de hacer pruebas unitarias sigue siendo valioso porque señala oportunidades para mejoras en el código. En general, si las pruebas son demasiado complicadas, el código subyacente probablemente puede usar algo de refactorización. En este caso, es doesProductExist una función doesProductExist se pueda refactorizar. Devolver las promesas de knex / bookshelf en lugar de convertirlas en devoluciones de llamada también sería una simplificación útil.

Pero a modo de comparación, aquí está mi opinión sobre cómo se vería la verdadera prueba unitaria del código existente:

var rewire = require(''rewire''); var sinon = require(''sinon''); var expect = require(''chai'').expect; var Promise = require(''bluebird''); var subscribeToUpdatesModule = rewire(''./service/subscribe_to_updates_module''); var subscribeToUpdates = subscribeToUpdatesModule.__get__(subscribeToUpdates); describe(''subscribeToUpdates'', function () { before(function () { var self = this; this.sandbox = sinon.sandbox.create(); var VorcuProduct = subscribeToUpdatesModule.__get__(''model'').VorcuProduct; this.saveStub = this.sandbox.stub(VorcuProduct.prototype, ''save''); this.saveStub.returns(this.saveResultPromise); this.fetchStub = this.sandbox.stub() this.fetchStub.returns(this.fetchResultPromise); this.sandbox.stub(VorcuProduct, ''where'', function () { return { fetch: self.fetchStub }; }) }); afterEach(function () { this.sandbox.restore(); }); it(''calls save when fetch of existing_model succeeds'', function (done) { var self = this; this.fetchResultPromise = Promise.resolve(''valid result''); this.saveResultPromise = Promise.resolve(''save result''); var callback = function (err, result) { expect(err).to.be.null; expect(self.saveStub).to.be.called; expect(result).to.equal(''save result''); done(); }; subscribeToUpdates({}, callback); }); // ... more it(...) blocks });


He estado utilizando las bases de datos en memoria Sqlite3 para realizar pruebas automatizadas con gran éxito. Mis pruebas tardan entre 10 y 15 minutos en ejecutarse contra MySQL, pero solo 30 segundos más o menos con una base de datos sqlite3 en memoria. Use :memory: para que su cadena de conexión utilice esta técnica.

Una nota sobre la prueba de la unidad : esto no es una prueba de unidad verdadera, ya que todavía estamos ejecutando una consulta en una base de datos. Esto es técnicamente una prueba de integración, sin embargo, se ejecuta dentro de un período de tiempo razonable y, si tiene una aplicación de consulta (como la mía), esta técnica será más efectiva para detectar errores que las pruebas unitarias.

Gotchas : Knex / Bookshelf inicializa la conexión al inicio de la aplicación, lo que significa que se mantiene el contexto entre las pruebas. Recomendaría escribir un script de creación / destrucción de esquema para que usted, y construya y destruya las tablas para cada prueba. Además, Sqlite3 es menos sensible a las restricciones de clave externa que MySQL o PostgreSQL, así que asegúrese de ejecutar su aplicación contra una de esas de vez en cuando para asegurarse de que sus restricciones funcionen correctamente.