'Jest test a function integrated with the ssh2-sftp-client library
I need to test a function that write a file from local path to remote path on an sftp machine using shh2-sftp-client library.
my own function is the following:
//fileshareAPI.js
saveFile: function saveFile(folder, filename, file) {
uploadValidateBody(folder, filename, file);
const Client = require('ssh2-sftp-client');
const sftp = new Client();
return sftp.connect(sftpConfig)
.then(() => {
console.log('connection OK')
fs.writeFile(filename, file, { encoding: 'base64' }, (err) => console.log(err));
console.log(`${basePath}${folder}`)
return sftp.mkdir(`/${basePath}${folder}`, true);
}).then(() => {
return sftp.put(filename, `/${basePath}${folder}/${filename}`);
}).then(() => {
fs.unlinkSync(filename);
return true;
}).catch((err) => {
console.log('an erro occurred')
throw new InternalServerError(5002, err.message)
}).finally(() => {return sftp.end()})
}
I created my own test class
const sftp = require('ssh2-sftp-client') //import of the class from the library
jest.mock('ssh2-sftp-client') //default mock. All methods are undefined
describe('test', () => {
beforeAll(() => {
sftp.mockImplementation(() => {
return {
connect: jest.fn().mockReturnValue(Promise.reject(new Error('error'))),
mkdir: jest.fn().mockReturnValue(Promise.resolve(true)),
put: jest.fn().mockReturnValue(Promise.resolve(true)),
end: jest.fn().mockReturnValue(Promise.resolve(true))
}
})
});
it('should throw exception', () => {
return expect(fileshareUtilities.saveFile('a', 'b', 'c')).rejects.toThrow('error')
});
});
Despite declaring the new constructor via the mockImplementation method, I always get the constructor returned by the default mock. In fact i get the following error:
TypeError: Cannot read property 'then' of undefined
65 | saveFile: function saveFile(folder, filename, file) {
66 | uploadValidateBody(folder, filename, file);
> 67 | return sftp.connect(sftpConfig)
| ^
68 | .then(() => {
69 | console.log('connection OK')
70 | fs.writeFile(filename, file, { encoding: 'base64' }, (err) => console.log(err));
at Object.saveFile (lib/apis/fileshare/fileshareAPI.js:67:16)
at Object.<anonymous> (test/fileshare.test.js:30:42)
How do I override the different constructor methods for each test, so that I can test the various points in the chain of functions called in saveFile?
Solution 1:[1]
I hope it will be useful to others, but I have found the solution. I always defined the mock by default, but then I invoked the mockImplementation() method on the instance of the ssh2-sftp-client library class, mocking the single functions. For each test I overwrite the return value of each function.
Here an example:
const sftp = require('ssh2-sftp-client');
const mockConnect = jest.fn();
const mockMkdir = jest.fn();
const mockPut = jest.fn();
const mockEnd = jest.fn();
const mockRename = jest.fn();
sftp.mockImplementation(() => {
return {
connect: mockConnect,
mkdir: mockMkdir,
put: mockPut,
rename: mockRename,
end: mockEnd
}
});
it('test mkdir', async() => {
mockConnect.mockReturnValue(Promise.resolve(true));
mockMkdir.mockReturnValue(Promise.reject(new Error('permission danied mkdir')))
await expect(fileshareUtilities.saveFile(inputFolder, inputFilename, 'file')).rejects.toThrow(new InternalServerError(5002, "permission danied mkdir"));
});
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | miah |