【问题标题】:How to test recursive function in Jest.js如何在 Jest.js 中测试递归函数
【发布时间】:2020-05-25 20:18:09
【问题描述】:

我有一个脚本来循环目录并匹配具有特定类型的文件。不幸的是,jest 在它结束之前通过了这个测试。我知道为什么,但我不知道如何让脚本等待循环结束。

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
                })
            }
        })
    })
})

【问题讨论】:

标签: javascript unit-testing asynchronous testing jestjs


【解决方案1】:

您可以在测试参数中传递done,并在测试结束时调用它。

您可以阅读有关异步测试的更多信息here

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);
        });
      }
    });
  });
});

【讨论】:

  • 它并不总是有效,因为断言也被递归调用并且 done 可能会被调用多次。例如,它可以首先调用完成,然后找到测试失败的文件
  • 那么就可以在foreach循环之后调用了。
  • 这是测试异步函数的基本思路。
  • 我已经更新了答案,请你试试这个。
  • 好的,我通过将它包装在 Promise 上来修复它。谢谢
【解决方案2】:

你应该使用fs.promises函数递归地列出你目录的内容以获得一个统一的文件列表。

将此函数与实际读取文件的任何代码分开进行单元测试。 (例如:您的 filename.matchreadFile 代码应与 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 对统一列表中的所有文件执行操作。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-23
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 2021-05-03
    • 1970-01-01
    相关资源
    最近更新 更多