I have a function that does a lot of things, but among them is that it copies a file to a special directory, does something with it (calls something to interact with that file without using the fs
module), and then deletes the copied file once finished.
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));
}
Since only myFunction()
is exported (it's the only thing that should be able to be directly interacted with), I have to unit test myOtherFunction()
and myIOFunction()
through it. Part of that is copyFileSync
and unlinkFileSync
.
My test looks something like this:
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();
...
});
The test is failing with the errors that neither mockCopyFile
nor mockUnlinkFile
is called. The problem is that the corresponding functions are called - I've stepped through the test with a debugger, and they execute without issue. So the problem must be that the spies aren't properly attaching themselves.
I don't know how to get them to be called. I've tried doing import * as fs from 'fs'
and fs.copyFileSync()
/fs.unlinkFileSync()
in the file being tested. I've tried putting the mocks in a beforeAll()
function. Neither solution helps. I'm mocking several other, not immediately relevant, method calls in the same test spec, and they're all working exactly as intended; it's only this one that isn't, and I can't figure out why.
My package.json
includes the following dependencies:
"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"
}
and my jasmine.json
looks like so:
{
"spec_dir": "dist",
"spec_files": [
"**/*[sS]pec.js"
],
"helpers": [
"helpers/**/*.js"
],
"stopSpecOnExpectationFailure": false,
"random": true
}
And 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"
]
}