从 Mock FS 开玩笑测试 Node JS 文件错误
Jest testing Node JS file error from Mock FS
我按照基本的例子,使用异步读取文件,无法测试文件读取失败。使用Mock-FS做测试,成功的都通过了,失败的会产生未处理的异常错误。
ReadFileContents.ts
import * as NodeJSFS from 'fs';
export async function ReadFileContents(Directory:string, FileName:string):Promise<string> {
return new Promise<string>((resolve, reject) => {
NodeJSFS.readFile(
`${Directory}/${FileName}`,
(error: NodeJS.ErrnoException | null, FileContents: Buffer) => {
if (error) {
reject(error);
} else {
resolve(FileContents.toString());
}
},
);
});
}
ReadFileContents.spec.ts
import * as MockFS from 'mock-fs';
import { ReadFileContents } from './read-file-contents';
describe('ReadFileContents', () => {
afterAll( async () => {
MockFS.restore();
});
afterEach( async () => {
MockFS.restore();
});
beforeEach( async () => {
MockFS( {
'datafiles': {
'abc.txt': '{ "FirstLine": "This is the first line", "LastLine": "This is the last line" }',
'abc.hdr': 'Server|MyServer',
}
}, {
// add this option otherwise node-glob returns an empty string!
createCwd: false
} );
});
it('should have the proper files in the mocked data', () => {
expect(MockFS.length).toBe(2);
});
it('should load the proper file data abc.txt', async () => {
ReadFileContents('./datafiles', 'abc.txt').then( FileContent => {
expect(FileContent).toContain('This is the first line');
});
});
it('should load the proper file data from abc.hdr', async () => {
ReadFileContents('./datafiles', 'abc.hdr').then( FileContent => {
expect(FileContent).toContain('Server');
});
});
// it('should return an exception when the file does not exist', async () => {
// expect(async () => await ReadFileContents('./datafiles', 'FileDoesNotExist.Missing')).not.toThrow();
// });
});
另外,这个测试也会出现同样的错误:
it('should return an exception when the file does not exist', async () => {
await expect(ReadFileContents('./datafiles', 'FileDoesNotExist.Missing'))
.rejects
.toThrow();
});
上面的错误处理,对于丢失的文件,生成以下错误:
node:internal/process/promises:245
triggerUncaughtException(err, true /* fromPromise */);
^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "Error: EBADF, bad file descriptor".] {
code: 'ERR_UNHANDLED_REJECTION'
如果没有错误条件测试,即使测试通过,我也会收到以下单元测试警告错误。
node:internal/process/promises:245
triggerUncaughtException(err, true /* fromPromise */);
^
[Error: EAGAIN: resource temporarily unavailable, read] {
errno: -11,
code: 'EAGAIN',
syscall: 'read'
}
在 catch 块中,您正在拒绝错误。错误应该是字符串类型,如您所期望的 return 字符串。
我通过对 的回答解决了这个问题。我更改了代码以使用 fs/promises 版本的 readFile。
我将代码更改为:
import * as NodeJSFSPromises from 'fs/promises';
import * as NodeJSPath from 'path';
export async function ReadFileContents(Directory:string, FileName:string):Promise<string> {
const PathAndFileName = NodeJSPath.format( { dir: Directory, base: FileName });
const FileContents$:Promise<Buffer> = NodeJSFSPromises.readFile(PathAndFileName);
const Contents:string = (await FileContents$).toString();
return Contents;
}
我按照基本的例子,使用异步读取文件,无法测试文件读取失败。使用Mock-FS做测试,成功的都通过了,失败的会产生未处理的异常错误。
ReadFileContents.ts
import * as NodeJSFS from 'fs';
export async function ReadFileContents(Directory:string, FileName:string):Promise<string> {
return new Promise<string>((resolve, reject) => {
NodeJSFS.readFile(
`${Directory}/${FileName}`,
(error: NodeJS.ErrnoException | null, FileContents: Buffer) => {
if (error) {
reject(error);
} else {
resolve(FileContents.toString());
}
},
);
});
}
ReadFileContents.spec.ts
import * as MockFS from 'mock-fs';
import { ReadFileContents } from './read-file-contents';
describe('ReadFileContents', () => {
afterAll( async () => {
MockFS.restore();
});
afterEach( async () => {
MockFS.restore();
});
beforeEach( async () => {
MockFS( {
'datafiles': {
'abc.txt': '{ "FirstLine": "This is the first line", "LastLine": "This is the last line" }',
'abc.hdr': 'Server|MyServer',
}
}, {
// add this option otherwise node-glob returns an empty string!
createCwd: false
} );
});
it('should have the proper files in the mocked data', () => {
expect(MockFS.length).toBe(2);
});
it('should load the proper file data abc.txt', async () => {
ReadFileContents('./datafiles', 'abc.txt').then( FileContent => {
expect(FileContent).toContain('This is the first line');
});
});
it('should load the proper file data from abc.hdr', async () => {
ReadFileContents('./datafiles', 'abc.hdr').then( FileContent => {
expect(FileContent).toContain('Server');
});
});
// it('should return an exception when the file does not exist', async () => {
// expect(async () => await ReadFileContents('./datafiles', 'FileDoesNotExist.Missing')).not.toThrow();
// });
});
另外,这个测试也会出现同样的错误:
it('should return an exception when the file does not exist', async () => {
await expect(ReadFileContents('./datafiles', 'FileDoesNotExist.Missing'))
.rejects
.toThrow();
});
上面的错误处理,对于丢失的文件,生成以下错误:
node:internal/process/promises:245
triggerUncaughtException(err, true /* fromPromise */);
^
[UnhandledPromiseRejection: This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). The promise rejected with the reason "Error: EBADF, bad file descriptor".] {
code: 'ERR_UNHANDLED_REJECTION'
如果没有错误条件测试,即使测试通过,我也会收到以下单元测试警告错误。
node:internal/process/promises:245
triggerUncaughtException(err, true /* fromPromise */);
^
[Error: EAGAIN: resource temporarily unavailable, read] {
errno: -11,
code: 'EAGAIN',
syscall: 'read'
}
在 catch 块中,您正在拒绝错误。错误应该是字符串类型,如您所期望的 return 字符串。
我通过对
我将代码更改为:
import * as NodeJSFSPromises from 'fs/promises';
import * as NodeJSPath from 'path';
export async function ReadFileContents(Directory:string, FileName:string):Promise<string> {
const PathAndFileName = NodeJSPath.format( { dir: Directory, base: FileName });
const FileContents$:Promise<Buffer> = NodeJSFSPromises.readFile(PathAndFileName);
const Contents:string = (await FileContents$).toString();
return Contents;
}