es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Sinon no actualiza el contador de llamadas cuando la función que está simulada se llama a través de una variable local.

Tengo esta función writeToFile la cual agrega o escribe según el argumento append. El appendFile y writeFile son de los módulos fs que estoy tratando de agregar a mis pruebas unitarias.
El problema en el siguiente código es que, al probarlo y crear stubs para appendFile y writeFile de fs, el contador de llamadas (callCount) no se incrementa si asigno las funciones append y write a una variable local func. Si solo llamo estas funciones directamente agregando una condición, las pruebas funcionan bien pero serían líneas de código adicionales y feas (según algunas personas).

Sería bueno si alguien pudiera explicar este comportamiento de sinon con la asignación de función a una variable local y si hay una solución sin cambiar la función en utils.js

Fragmento de código de utils.js:

export async function writeToFile(path, data, append) {
  const func = append ? fs.appendFile : fs.writeFile;
  return func(path, data, (err) => {
    if (err) { logger.error(err); }
  });
}

Fragmento de código de test.js:

it('Write to file', async () => {
    const append = sinon.stub(fs, 'appendFile');
    const write = sinon.stub(fs, 'writeFile');

    await writeToFile('path', 'buffer', false);
    expect(append.callCount).to.equal(0);
    expect(write.callCount).to.equal(1);

    await writeToFile('path', 'buffer', true);
    expect(append.callCount).to.equal(1);
    expect(write.callCount).to.equal(1);
});

aquí puedes ver la imagen.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    El problema es que la variable func en la función writeToFile se le asigna una referencia a fs.appendFile o fs.writeFile, pero los stubs append y write se crean antes de que se llame a la función, por lo que no tienen una referencia a la función correcta en el momento en que se llaman. Es por eso que el callCount no se incrementa cuando se utiliza la variable func.

    Una solución a este problema es usar el método callsFake del stub para reemplazar la implementación de la variable func con el stub, de la siguiente manera:

    it('Escribir en archivo', async () => {
        const append = sinon.stub(fs, 'appendFile').callsFake((path, data, callback) => {
            return callback(null);
        });
        const write = sinon.stub(fs, 'writeFile').callsFake((path, data, callback) => {
            return callback(null);
        });
    
        await writeToFile('ruta', 'buffer', false);
        expect(append.callCount).to.equal(0);
        expect(write.callCount).to.equal(1);
    
        await writeToFile('ruta', 'buffer', true);
        expect(append.callCount).to.equal(1);
        expect(write.callCount).to.equal(1);
    });
    

    Esto reemplazará la implementación de func con el stub, que seguirá correctamente el número de veces que se llama.

    Otra solución es pasar el módulo fs como argumento a la función writeToFile, para que los stubs puedan crearse con la referencia correcta a fs.appendFile o fs.writeFile. Esto requeriría cambiar la firma de la función writeToFile, lo cual puede que no sea deseable.

    En general, el uso del método callsFake es una solución simple y efectiva a este problema.

Comments are closed.