我需要在一个类中模拟DNS
节点模块,但是由于该类包含在类中,因此我不确定该如何做。这是该类的示例...
import { lookup } from 'dns';
class Foo {
// ...
protected async _bar(IP: string) {
// I want to mock "lookup"
await new Promise<undefined>((resolve, reject) => {
lookup(IP, (err, addr) => {
if (err) reject(new Error('DNS Lookup failed for IP_ADDR ' + IP));
resolve();
});
});
// If dns found then return true
return true;
}
// ...
}
我想创建一个包含类似于以下内容的测试的测试文件foo.spec.ts
:
import { Foo } from './Foo';
describe('Foo', () => {
it('Bar Method returns true on success', () => {
const test = new Foo();
expect(test._bar('192.168.1.1')).resolves.toBeTruthy();
});
});
由于类定义与测试本身位于单独的文件中,因此我不确定如何在类lookup
中模拟Foo
调用。
任何帮助将不胜感激!
答案 0 :(得分:1)
来自玩笑的tutorial,
jest.mock('./sound-player', () => {
return function() {
return {playSoundFile: () => {}};
};
});
所以您可以像jest.mock('dns', () => { ... });
答案 1 :(得分:1)
您使用lookup
的方式将不起作用,因为它不会返回Promise
...
...但是您可以使用util.promisify
将其转换为确实返回Promise
的版本。
代码最终看起来像这样:
import { lookup as originalLookup } from 'dns'; // <= import original lookup...
import { promisify } from 'util';
const lookup = promisify(originalLookup); // <= ...and promisify it
export class Foo {
async _bar(IP: string) {
await lookup(IP).catch(err => { throw new Error('Failed'); });
return true;
}
}
然后您可以像下面这样使用lookup
在测试中模拟jest.mock
:
import { Foo } from './Foo';
jest.mock('dns', () => ({
lookup: (hostname, callback) => {
hostname === 'example.com' ? callback() : callback('error');
}
}))
describe('Foo', () => {
it('Bar Method returns true on success', async () => {
const test = new Foo();
await expect(test._bar('example.com')).resolves.toBeTruthy(); // Success!
await expect(test._bar('something else')).rejects.toThrowError('Failed'); // Success!
});
});
请注意,由于需要提升并运行jest.mock
的调用,因此需要使用jest.spyOn
(而不是jest.mock
之类的东西来创建模拟)。导入Foo.js
之前,该模拟必须就位,因为它的第一件事是创建并存储承诺的lookup
。