Как проверить рекурсивную функцию в Jest. js - PullRequest
2 голосов
/ 10 февраля 2020

У меня есть скрипт для зацикливания каталогов и сопоставления файлов с указанным типом c. К сожалению, шутка проходит этот тест, прежде чем он заканчивается. Я знаю почему, но я не знаю, как сделать скрипт для ожидания окончания цикла.

import fs from 'fs'
const path = require('path');

describe('something', () => {
    it('should something', () => {
        const traverseDir = (dir, callback) => {
            fs.readdirSync(dir).forEach(file => {
                let fullPath = path.join(dir, file);
                if (fs.lstatSync(fullPath).isDirectory()) {
                    callback(fullPath)
                    traverseDir(fullPath, callback);
                } else {
                    callback(fullPath)
                }
            });
        }

        traverseDir('src/', (fullPath) => {
            const splitted = fullPath.split('/')
            const filename = splitted[splitted.length - 1]
            if (filename.match(/.*.foo/)) {
                fs.readFile(fullPath, 'utf8', (err, data) => {
                    expect(err).toBe(null)
                    // some assertion
                })
            }
        })
    })
})

Ответы [ 2 ]

1 голос
/ 10 февраля 2020

Вы должны использовать функции fs.promises для рекурсивного перечисления содержимого вашего каталога для получения единого списка файлов.

Модульное тестирование этой функции отдельно от любого кода, который фактически читает файл. (Например: ваш код filename.match и readFile должен быть проверен отдельно от кода traverseDir.)

Пример асинхронного обхода каталогов для получения единого списка файлов:

Этот асинхронный allFilesIn Функция рекурсивно получает все файлы в каталоге и возвращает список в виде одного массива с полными (относительными) путями.

const fs = require('fs').promises;
const path = require('path');

const allFilesIn = async (dir, results = []) => {
  const files = await fs.readdir(dir);
  for (file of files) {
    const fullPath = path.join(dir, file);
    const stat = await fs.stat(fullPath);
    if (stat.isDirectory()) {
      await allFilesIn(fullPath, results);
    } else {
      results.push(fullPath);
    }
  }
  return results;
}

// Example call:
allFilesIn('src/').then(files => {
  console.log(files); // e.g.:  [ 'src\\foo.cpp', 'src\\bar.cpp', 'src\\include\\foo.h' ]
});

После того, как у вас будет один массив из всех файлов, должно быть легко используйте один forEach, чтобы сделать что-то для всех файлов в объединенном списке.

1 голос
/ 10 февраля 2020

Вы можете передать done в тестовом параметре и вызвать его по окончании теста.

Подробнее об asyn c testing можно прочитать здесь .

import fs from "fs";
const path = require("path");

describe("something", () => {
  it("should something", done => {
    const traverseDir = (dir, callback) => {
      fs.readdirSync(dir).forEach(file => {
        let fullPath = path.join(dir, file);
        if (fs.lstatSync(fullPath).isDirectory()) {
          callback(fullPath);
          traverseDir(fullPath, callback);
        } else {
          callback(fullPath);
        }
      });

         done(); // Call done to tell Jest that the test has finished.
    };

    traverseDir("src/", fullPath => {
      const splitted = fullPath.split("/");
      const filename = splitted[splitted.length - 1];
      if (filename.match(/.*.foo/)) {
        fs.readFile(fullPath, "utf8", (err, data) => {
          expect(err).toBe(null);
        });
      }
    });
  });
});

...