问题描述
我想用玩笑对单元 zip.adapter.ts 进行单元测试。我尝试了许多其他方法来模拟/存根adm-zip程序包,但无济于事。
我首先尝试了ts-mock-imports,但是如果我尝试模拟adm-zip,它总是会失败。然后我尝试了sinon,但是它要么无法存根adm-zip,要么就没有存根。 我的最后一招是将sinon与proxyquire结合使用,但这似乎也不起作用....
有人知道为什么这行不通吗?当测试调用 unzip 方法时,其中的代码仍然使用真正的adm-zip实现...
(我知道单元测试没有多大意义,因为一切都被模拟了,但是由于我无法更改的测试覆盖率规则,我必须这样做)
zip.adapter.ts
import * as admZip from 'adm-zip';
export class ZipAdapter {
constructor() {}
unzip(zip: Buffer,path: string) {
const unzip = new admZip(zip);
unzip.extractAllTo(path,true);
}
}
zip.adapter.spec.ts
import * as sinon from 'sinon';
import { ZipAdapter } from './zip.adapter';
import * as proxyquire from 'proxyquire';
describe('Zip Adapter',() => {
let zipAdapter: ZipAdapter;
beforeEach(() => {
const admZipInstance = { extractAllTo: sinon.stub() };
const admZipStub = sinon.stub().callsFake(() => admZipInstance);
const moduleStub = proxyquire('./zip.adapter.ts',{ 'adm-zip': admZipStub });
zipAdapter = new moduleStub.ZipAdapter();
});
it('should be defined',() => {
expect(zipAdapter).tobedefined();
});
it('should have called extractAllTo',() => {
zipAdapter.unzip(Buffer.from(''),'test');
});
});
更新:
我在Jest上进行了测试,但前提是我需要我的模块。如果我在没有require()的情况下使用导入,则模拟无法正常工作。是否可以摆脱require()而仅使用import?
import { ZipAdapter } from './zip.adapter';
describe('Zip Adapter',() => {
let zipAdapter: ZipAdapter;
let admZipExtractAllMock: jest.Mock<any,any>;
beforeEach(() => {
const admZipMock = jest.fn();
admZipExtractAllMock = jest.fn();
admZipMock.mockImplementation(() => {
return { extractAllTo: admZipExtractAllMock };
});
jest.mock('adm-zip',() => admZipMock);
const zipAdapterModule = require('./zip.adapter');
zipAdapter = new zipAdapterModule.ZipAdapter();
});
it('should be defined',() => {
zipAdapter.unzip('unit','test');
expect(admZipExtractAllMock.mock.calls.length).toBe(1);
});
});
解决方法
顶级导入仅导入const dispatcher = connection.play(ytdl(YOUR_URL,{ filter: 'audioonly' }),{seek:35})
类型,因此首次使用int
进行导入时将对其进行评估。如果在导入后用int
模拟,则不会影响导入的模块。
如果需要对所有测试进行模拟,则应对其进行模拟并在顶层导入:
int
顶部的 ZipAdapter
悬挂在require
上方。 jest.mock
间谍暴露为命名导出,以便能够随时更改实现,最好使用import * as zipAdapterModule from './zip.adapter';
jest.mock('adm-zip',() => {
let admZipExtractAllMock = jest.fn();
return {
__esModule: true,admZipExtractAllMock,default: jest.fn(() => ({ extractAllTo: admZipExtractAllMock }))
});
方法,以不影响其他测试。
如果某些测试不需要模拟它,或者Jest spy API不足以更改实现,则需要在测试中将其jest.mock
进行模拟,并以import
进行导入,如图所示。 OP。在这种情况下,应添加admZipExtractAllMock
以允许重新导入模拟模块。