Búsqueda de sitios web

javascript - ¿Cómo realizar pruebas unitarias a un módulo de Node.js que requiere otros módulos y cómo simular la función global require?


Este es un ejemplo trivial que ilustra la raíz de mi problema:

var innerLib = require('./path/to/innerLib');

function underTest() {
    return innerLib.doComplexStuff();
}

module.exports = underTest;

Estoy tratando de escribir una prueba unitaria para este código. ¿Cómo puedo simular la necesidad de innerLib sin simular la función require completamente?

Así que esto soy yo tratando de simular el require global y descubriendo que ni siquiera funcionará para hacer eso:

var path = require('path'),
    vm = require('vm'),
    fs = require('fs'),
    indexPath = path.join(__dirname, './underTest');

var globalRequire = require;

require = function(name) {
    console.log('require: ' + name);
    switch(name) {
        case 'connect':
        case indexPath:
            return globalRequire(name);
            break;
    }
};

El problema es que la función require dentro del archivo underTest.js en realidad no ha sido simulada. Todavía apunta a la función global require. Así que parece que solo puedo simular la función require dentro del mismo archivo en el que estoy haciendo la simulación. Si uso la require global para incluir cualquier cosa, incluso después de haber sobrescrito la copia local, los archivos requeridos todavía tendrán la referencia a la require global.

Respuesta #1

¡Ahora puedes!

Publiqué proxyquire, que se encargará de sobrescribir el require global dentro de tu módulo mientras lo estás probando.

Esto significa que no necesitas hacer cambios en tu código para inyectar mocks en los módulos requeridos.

Proxyquire tiene una API muy simple que permite resolver el módulo que estás tratando de probar y pasar mocks/stubs para sus módulos requeridos en un solo paso simple.

@Raynos tiene razón en que tradicionalmente tenías que recurrir a soluciones no muy ideales para lograr eso o hacer desarrollo de abajo hacia arriba en su lugar

Cuál es la razón principal por la que creé proxyquire: permitir el desarrollo dirigido por pruebas de arriba hacia abajo sin ninguna complicación.

Echa un vistazo a la documentación y a los ejemplos para evaluar si se ajustará a tus necesidades.

Respuesta #2

Una mejor opción en este caso es simular los métodos del módulo que se devuelve.

Para bien o para mal, la mayoría de los módulos de node.js son singulares; dos fragmentos de código que hacen require() del mismo módulo obtienen la misma referencia a ese módulo.

Puedes aprovechar esto y usar algo como sinon para simular elementos que son requeridos. La prueba de mocha sigue:

// in your testfile
var innerLib  = require('./path/to/innerLib');
var underTest = require('./path/to/underTest');
var sinon     = require('sinon');

describe("underTest", function() {
  it("does something", function() {
    sinon.stub(innerLib, 'toCrazyCrap').callsFake(function() {
      // whatever you would like innerLib.toCrazyCrap to do under test
    });

    underTest();

    sinon.assert.calledOnce(innerLib.toCrazyCrap); // sinon assertion

    innerLib.toCrazyCrap.restore(); // restore original functionality
  });
});

Sinon tiene una buena integración con Chai para hacer afirmaciones, y escribí un módulo para integrar Sinon con Mocha para permitir una limpieza más fácil de spies/stubs (para evitar la contaminación de pruebas).

Tenga en cuenta que underTest no se puede simular de la misma manera, ya que underTest devuelve solo una función.

Otra opción es usar mocks de Jest. Haz un seguimiento en su página

Respuesta #3

Uso mock-require. Asegúrate de definir tus mocks antes de require el módulo que se va a probar.

Artículos relacionados