我有一个函数可以做很多事情,但其中之一是它将一个文件复制到一个特殊的目录中,使用它做一些事情(调用一些东西来与该文件进行交互而不使用fs模块),然后在完成后删除复制的文件。
import { copyFileSync, unlinkSync } from 'fs';
myOtherFunction(path: string) {
...
}
myIOFunction(somePath: string) {
var copyPath = resolve('otherDir/file2.csv');
copyFileSync(somePath, copyPath);
try {
myOtherFunction(copyPath);
} finally {
unlinkFileSync(copyPath);
}
}
export myFunction() {
...
myIOFunction(resolve('file1.csv));
}由于只有myFunction()是导出的(这是唯一可以直接交互的东西),所以我必须通过它对myOtherFunction()和myIOFunction()进行单元测试。其中一部分是copyFileSync和unlinkFileSync。
我的测试看起来是这样的:
import * as fs from 'fs';
import myFunction from './myFile';
...
it("tests something involving input/output", () => {
mockCopyFile = spyOn(fs, 'copyFileSync');
mockUnlinkFile = spyOn(fs, 'unlinkSync');
...
myFunction();
expect(mockCopyFile).toHaveBeenCalledWith(resolve('file1.csv'), resolve('otherDir/file2.csv'));
expect(mockUnlinkFile).toHaveBeenCalled();
...
});测试失败了,没有调用mockCopyFile或mockUnlinkFile的错误。问题是调用了相应的函数--我已经用调试器完成了测试,它们执行时没有问题。所以问题一定是间谍们没有正确地依附自己。
我不知道怎么叫他们。我尝试在正在测试的文件中执行import * as fs from 'fs'和fs.copyFileSync()/fs.unlinkFileSync()。我已经尝试过将模拟放在beforeAll()函数中。这两种解决方案都没有帮助。我在嘲弄同一测试规范中的其他几个方法调用,它们都完全按照预期工作;只有这个方法没有调用,我不知道为什么。
我的package.json包括以下依赖项:
"scripts": {
"test": "tsc && jasmine",
},
"devDependencies": {
"@types/jasmine": "^3.5.10",
"@types/node": "^13.7.7",
"@types/pg": "^7.14.3",
"copyfiles": "^2.2.0",
"jasmine": "^3.5.0",
"jasmine-core": "^3.5.0",
"jasmine-ts": "^0.3.0",
"js-yaml": "^3.13.1",
"mock-fs": "^4.11.0",
"morgan": "^1.10.0",
"nodemon": "^2.0.2",
"swagger-ui-express": "^4.1.3",
"ts-node": "^8.7.0",
"typescript": "^3.8.3"
},
"dependencies": {
"@types/express": "^4.17.3",
"chokidar": "^3.3.1",
"cors": "^2.8.5",
"csv-writer": "^1.6.0",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"murmurhash": "0.0.2",
"pg": "^7.18.2",
"pg-format": "^1.0.4",
"winston": "^3.2.1"
}我的jasmine.json看起来是这样的:
{
"spec_dir": "dist",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": true
}和tsconfig
{
"compilerOptions": {
"experimentalDecorators": true,
"module": "commonjs",
"esModuleInterop": true,
"target": "es6",
"moduleResolution": "node",
"sourceMap": true,
"outDir": "dist",
"typeRoots": [
"node_modules/@types",
"node_modules/@types/node"
],
},
"lib": [
"es2015"
]
}发布于 2020-04-01 19:14:54
Jasmine spyOn模拟函数返回一个Spy类对象,它不表示任何函数调用,但它有用于模拟该函数的助手方法。您必须直接调用expect到fs.<function>,以检查它是否被调用:
import * as fs from 'fs';
import * as path from 'path';
import { myFunction } from '../src/myFunction';
describe('MyFunc', () => {
it("tests something involving input/output", () => {
spyOn(fs, 'copyFileSync');
spyOn(fs, 'unlinkSync');
myFunction();
expect(fs.copyFileSync).toHaveBeenCalledWith(
path.resolve('file1.csv'),
path.resolve('otherDir/file2.csv')
);
expect(fs.unlinkSync).toHaveBeenCalled();
});
});您可以使用以下GitHub repo:https://github.com/clytras/fs-jasminte-ts-mocking测试一个简单的复制示例
git clone https://github.com/clytras/fs-jasminte-ts-mocking.git
cd fs-jasminte-ts-mockin
npm i
npm run test更新
看起来您的esModuleInterop设置为true在tsconfig.json中。这意味着当您的import * as fs from 'fs'不保留fs对象的一个实例时。
您可以将esModuleInterop设置为false,并让测试与toHaveBeenCalled和toHaveBeenCalledWith一起通过,但这可能会破坏项目的其他一些功能。您可以阅读更多关于esModuleInterop在这里做什么的文章,Understanding esModuleInterop in tsconfig file。
如果不想将esModuleInterop设置为false,则必须导入fs,如下所示的ES6 Javascript中所示:
import fs from 'fs'; // Use plain default import instead of * as
import path from 'path';
import { myFunction } from '../src/myFunction';
describe('MyFunc', () => {
it("tests something involving input/output", () => {
spyOn(fs, 'copyFileSync');
spyOn(fs, 'unlinkSync');
myFunction();
expect(fs.copyFileSync).toHaveBeenCalledWith(
path.resolve('file1.csv'),
path.resolve('otherDir/file2.csv')
);
expect(fs.unlinkSync).toHaveBeenCalled();
});
});我还注意到您的配置文件中缺少以下内容:
如果您不使用
jasmine-console-reporter:- `npm i -D jasmine-console-reporter`
- Change `test` script inside `package.json` to be `"test": "tsc && jasmine --reporter=jasmine-console-reporter"`
jasmine.json,将ts-node/register/type-check.js添加到助手中,如:{ ..。"helpers":"helpers/**/*.js","../node_modules/ts-node/register/type-check.js“,}
现在你的测试应该通过了。
https://stackoverflow.com/questions/60934298
复制相似问题