首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >用Jest测试文件系统?

用Jest测试文件系统?
EN

Stack Overflow用户
提问于 2016-12-12 23:54:29
回答 3查看 12.5K关注 0票数 9

我正在使用mock-fs来尝试测试我编写的Webpack插件,它修改了我的文件系统上的一个文件。

下面是一个测试:

代码语言:javascript
复制
test('writes chunks to build/assets.json if no json file present', () => {
   mockFs({
    [buildDir]: {},
  });

  const stats = new Stats({
    assetsByChunkName: {
      main: 'main.somecrazyhash12341213445345.js',
    },
  });
  const compiler = new Compiler(stats);
  const plugin = new ChunksToJsonPlugin(config);

  expect(fs.existsSync(assetFilePath)).toBe(false);

  plugin.apply(compiler);
  compiler.execHandler();

  expect(fs.existsSync(assetFilePath)).toBe(true);
  expect(fs.readFileSync(assetFilePath, 'utf-8')).toEqual(
    JSON.stringify({
      main: 'main.somecrazyhash12341213445345.js',
    })
  );

  mockFs.restore();
});

当我单独运行它时,它工作得很好,但是当我作为套件的一部分运行它时,其他测试(不使用mock-fs)中断。

ss http://d.pr/i/z2ne+

我注意到mock-fs在堆栈跟踪中,这使我相信文件系统也在那些测试中被模拟(我不想)。

mock-fs指出:

模拟-fs@4发行版将包含中断的更改。这个库现在不再覆盖内置fs模块的所有方法,而是覆盖process.binding('fs')。此更改的目的是避免与覆盖fs方法的其他库(例如graceful-fs)发生冲突,并使之能够使用多个Node版本,而无需维护Node的fs模块的复制和稍微修改的版本。

我不太了解process.binding是如何工作的,特别是因为它与Jest并行运行测试有关,但我觉得这是核心问题。

我怎么才能把这事做好?是否有另一种不使用mock-fs测试此行为的方法?

EN

回答 3

Stack Overflow用户

发布于 2018-03-07 15:40:15

如果确实需要对文件系统进行测试,并且模拟文件系统会减少测试的值,那么您可以对自己的文件夹运行每个单独的测试,如下所示:

步骤1:声明基本文件夹

代码语言:javascript
复制
const DIR_BASE = path.resolve(__dirname, '__fixtures__/mytestedmodule');

步骤2:为每个测试创建一个唯一的子文件夹名

代码语言:javascript
复制
it('should ...', async () => {
  const DIR_ID = md5('should ...');
  const DIR = path.resolve(DIR_BASE, `data${DIR_ID}`);
  await mytestedmodule(DIR);
  expect(...);
});
  • 此处的md5用于创建测试名称的唯一散列,以便测试可以彼此独立运行。
  • 注意,下一步将使用data${DIR_ID}:data作为后测试清理的模式。

步骤3:清除所有尚未清除的文件夹

代码语言:javascript
复制
afterAll(async () => {
  const folders =
    (await fs.readdir(DIR_BASE))
      .filter((folder) => folder.match('data'));
  const promises = [];
  for (const folder of folders) {
    promises.push(fs.remove(path.resolve(DIR_BASE, folder)));
  }
  return Promise.all(promises);
});

只要只有一个Jest runner实例在文件夹上运行,此解决方案就能工作。如果需要并行地对应用程序进行多次测试,则必须在存储库的副本上运行测试。请记住,在windows上,对文件夹的读取仍然存在限制,因此,如果您的多个测试需要读取同一个文件夹,那么您很可能需要为每个测试创建不同的源文件夹。

票数 4
EN

Stack Overflow用户

发布于 2016-12-13 08:10:55

好的,所以我可以使用依赖注入(DI),放弃mock-fs,转而使用memfs

代码语言:javascript
复制
import memfs from 'memfs';

// ...

test('writes chunks to build/assets.json if no json file present', () => {
  // eslint-disable-next-line new-parens
  const fs = new memfs.Volume;

  fs.mountSync(buildDir, {});

  // same as before

  const plugin = new ChunksToJsonPlugin(config, fs);
  // ------------------------------------------ ^^

  expect(fs.existsSync(assetFilePath)).toBe(false);

  // same as before

  expect(fs.existsSync(assetFilePath)).toBe(true);
  expect(fs.readFileSync(assetFilePath, 'utf-8')).toEqual(
    JSON.stringify({
      main: 'main.somecrazyhash12341213445345.js',
    })
  );
});

相应地,我的ChunksToJsonPlugin API也必须进行更改,以便在运行live时传入实际的fs模块:

代码语言:javascript
复制
import fs from 'fs';

// ...

new ChunksToJsonPlugin(config, fs)

这是可行的,现在我的测试不关心并行/串行运行,但我觉得在这个过程中我可能会违背一些NodeJS约定。通常,在使用系统导入时,我没有看到多少DI,所以我担心仅仅为了测试而使用这种模式。

仍然可以知道在mock-fs中这是否可能,或者DI实际上是否是正确的方法。

票数 2
EN

Stack Overflow用户

发布于 2019-03-26 18:57:41

我今天遇到了一个类似的问题,结果是我的设置和拆卸方法影响了其他测试套件,因为它们并行运行。

要防止出现这种情况,请在运行测试套件时尝试添加以下标志。

代码语言:javascript
复制
--runInBand

代码语言:javascript
复制
jest --runInBand
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/41111620

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档