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.

Prueba unitaria de una función generadora asíncrona en Jest.

Me gustaría escribir una prueba unitaria para una función generadora, pero no puedo pasar un objeto de flujo de lectura correctamente simulado (ReadStream).

Función que se puede probar:

public async * readChunks(file: string, chunkSize: number): AsyncIterableIterator<buffer> {
  if (!this.cwd) throw new Error('¡No se ha establecido el directorio de trabajo!');

  const readStream: ReadStream = fs.createReadStream(path.join(this.cwd, file), {
    highWaterMark: chunkSize
  });

  for await (const chunk of readStream) yield chunk;
}

Implementación fallida (Intenté diferentes simulaciones de createReadStream, pero sin éxito):

describe('Work Dir Utils', () => {
  jest.mock('fs');

  let workDirUtils: WorkDirUtils;

  beforeEach(() => {
    (os.tmpdir as jest.Mock).mockReturnValue('/tmp');
    (fs.mkdtempSync as jest.Mock).mockReturnValue('/tmp/folder/pref-rand');
    (fs.createReadStream as jest.Mock).mockReturnValue({});
    workDirUtils = new WorkDirUtils();
    workDirUtils.createTempDir('pref-');
  });

  afterEach(() => {
    jest.clearAllMocks();
  });

  it('should read chunks of a file using generator', async () => {
    for await (const chunk of workDirUtils.readChunks(
      path.join(__dirname, './fixtures/manifest.ts'),
      1024 * 1024 * 1024
    )) {
      expect(chunk).toBeInstanceOf(Buffer);
    }
  });
});

¿Alguna sugerencia?

Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Para simular correctamente el método createReadStream en este escenario, puedes utilizar la función jest.mock con el método mockImplementation para crear un objeto ReadStream simulado que devuelve datos simulados. Aquí está una implementación actualizada para el caso de prueba:

    describe('Work Dir Utils', () => {
      jest.mock('fs');
    
      let workDirUtils: WorkDirUtils;
      let readStream: any; // define una variable para almacenar el objeto ReadStream simulado
    
      beforeEach(() => {
        (os.tmpdir as jest.Mock).mockReturnValue('/tmp');
        (fs.mkdtempSync as jest.Mock).mockReturnValue('/tmp/folder/pref-rand');
        readStream = {
          // define las propiedades/métodos necesarios para el objeto ReadStream
          on: jest.fn(),
          pause: jest.fn(),
          resume: jest.fn(),
        };
        (fs.createReadStream as jest.Mock).mockReturnValue(readStream);
        workDirUtils = new WorkDirUtils();
        workDirUtils.createTempDir('pref-');
      });
    
      afterEach(() => {
        jest.clearAllMocks();
      });
    
      it('should read chunks of a file using generator', async () => {
        const testData = Buffer.from('test data'); // define algunos datos de prueba para devolver desde el flujo
        readStream.on.mockImplementation((event: string, cb: () => void) => {
          if (event === 'data') cb(testData);
          if (event === 'end') cb();
        }); // define el comportamiento del objeto ReadStream cuando se desencadenan eventos
        const result = workDirUtils.readChunks(
          path.join(__dirname, './fixtures/manifest.ts'),
          1024 * 1024 * 1024
        );
        const chunk = await result.next(); // desencadena manualmente el generador para obtener el primer fragmento
        expect(chunk.value).toEqual(testData);
        expect(chunk.done).toBe(false);
        readStream.pause(); // pausa el flujo para simular el comportamiento asíncrono
        const end = await result.next(); // desencadena manualmente el generador para obtener el resultado final
        expect(end.done).toBe(true);
      });
    });
    

    En esta implementación, creamos una variable readStream para almacenar el objeto ReadStream simulado, y definimos sus propiedades/métodos para que coincidan con el comportamiento necesario para el caso de prueba. Luego utilizamos el método mockImplementation para definir el comportamiento del método on cuando se desencadenan eventos, de modo que podamos desencadenar manualmente el generador y obtener los resultados esperados. Por último, agregamos afirmaciones para asegurarnos de que se devuelven los datos de prueba y el generador sale correctamente del bucle.

Comments are closed.