我想用jest对类zip.adapter.ts进行单元测试。我尝试了许多不同的方法来模拟/存根adm-zip包,但是没有什么效果。
我第一次尝试T-模拟-进口,但如果我试图模仿adm-zip,它总是失败的。然后,我尝试了西农,但它不是没有存根adm-zip,就是没有存根。我的最后一招是把sinon和丙氧奎尔结合起来,但这似乎也行不通.
有人知道为什么这不管用吗?当测试调用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 { 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', () => {
expect(zipAdapter).toBeDefined();
});
it('should have called extractAllTo', () => {
zipAdapter.unzip('unit', 'test');
expect(admZipExtractAllMock.mock.calls.length).toBe(1);
});
});发布于 2020-11-04 16:44:46
顶级导入仅导入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.mock悬挂在import上方。admZipExtractAllMock间谍被公开为命名导出,以便能够随时更改实现,最好使用Once方法不影响其他测试。
如果某些测试不需要对其进行模拟,或者Jest间谍API不足以更改实现,则需要使用jest.mock对其进行模拟,并在如OP所示的测试中使用require导入它。在这种情况下,应该添加jest.resetModules以允许重新导入模拟模块。
https://stackoverflow.com/questions/64676413
复制相似问题