nee*_*zer 7 unit-testing node.js jestjs
我正在mock-fs尝试测试我编写的Webpack插件,它修改了我文件系统上的文件.
这是测试:
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();
});
Run Code Online (Sandbox Code Playgroud)
当我单独运行它时,它的工作效果非常好,但是当我将它作为套件的一部分运行时,其他测试(不使用mock-fs)会中断.
我注意到mock-fs在堆栈跟踪中,这让我相信文件系统也在那些测试中被嘲笑(我不想要).
mock-fs 说:
mock-fs @ 4版本将包含重大更改.
fs现在覆盖库,而不是覆盖内置模块的所有方法process.binding('fs').此更改的目的是避免与覆盖fs方法(例如graceful-fs)的其他库发生冲突,并且可以在不维护Nodefs模块的复制和略微修改版本的情况下使用多个Node版本.
我不太清楚如何process.binding工作,特别是因为它与Jest并行运行测试有关,但我觉得这是核心问题.
我怎样才能做到这一点?有没有其他方法来测试这种行为而不使用mock-fs?
如果您确实需要针对文件系统进行测试,并且模拟文件系统会降低测试的价值,那么您可以针对其自己的文件夹运行每个单独的测试,如下所示:
const DIR_BASE = path.resolve(__dirname, '__fixtures__/mytestedmodule');
Run Code Online (Sandbox Code Playgroud)
it('should ...', async () => {
const DIR_ID = md5('should ...');
const DIR = path.resolve(DIR_BASE, `data${DIR_ID}`);
await mytestedmodule(DIR);
expect(...);
});
Run Code Online (Sandbox Code Playgroud)
data${DIR_ID}:数据将在下一步中用作测试后清理的模式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);
});
Run Code Online (Sandbox Code Playgroud)
只要文件夹上仅运行一个 Jest 运行程序实例,此解决方案就可以工作。如果您需要多次并行测试应用程序,则必须在存储库的副本上运行测试。请记住,在 Windows 上,读取文件夹仍然存在限制,因此,如果您的多个测试需要读取同一文件夹,则您很可能需要为每个测试使用不同的源文件夹。
好的,所以我可以通过依赖注入(DI)来实现这一点,而mock-fs放弃memfs:
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',
})
);
});
Run Code Online (Sandbox Code Playgroud)
相应地,我的 API也必须更改,以便我在实时运行时ChunksToJsonPlugin传递实际模块:fs
import fs from 'fs';
// ...
new ChunksToJsonPlugin(config, fs)
Run Code Online (Sandbox Code Playgroud)
这是可行的,现在我的测试不关心并行/串行运行,但我觉得我可能会在这个过程中违反一些 NodeJS 约定。一般来说,我在使用系统导入时没有看到太多的 DI,所以我有点担心仅仅为了测试而使用这种模式。
仍然愿意知道这是否可以通过 DI 实现mock-fs,或者 DI 是否实际上是正确的方法。
| 归档时间: |
|
| 查看次数: |
4260 次 |
| 最近记录: |