在玩笑测试中调用 new class() 后没有创建新的 class 实例
No new class instance created after calling new class() within a jest test
问题
在单元测试中创建新的 class 实例不会触发构造函数。
详情
我正在尝试测试在给出错误的服务器 IP 时是否抛出错误,但是当我尝试创建一个应该抛出错误的 class 的新实例时它不起作用。
我要测试的 class 是:
export class ClassA {
private readonly _redisServerIP = config.redisServerIP;
private readonly _redisServerPort = config.redisServerPort;
constructor() {
console.log(this._redisServerIP);
this.configure();
}
private configure(): void {
this._redisSub = redis.createClient({host: this._redisServerIP, port: this._redisServerPort});
this._redisSub.on('error', (error) => {
if (error.code === "ECONNREFUSED") {
this._logger.error('Could not create a redisSub, is the redis server running?');
}
throw new Error('Something bad happened');
});
}
}
这是我的测试代码:
import * as constants from '../src/config/config';
let socket;
let classA;
let httpServerAddr;
beforeAll((done) => {
classA = new ClassA();
httpServerAddr = classA.getServerIp();
done();
});
afterAll((done) => {
done();
});
beforeEach((done) => {
});
afterEach((done) => {
done();
});
describe('Socket.io redis testing', () => {
test('should fail due to invalid serverIP', () => {
constants.config.redisServerIP = "0.0.0.0";
classA = null;
expect(() => {
classA = new ClassA();
}).toThrow();
});
});
我在我的节点控制台中只看到一次服务器 ip,由于以下错误导致测试失败:
expect(function).toThrow(undefined)
Expected the function to throw an error.
But it didn't throw anything.
这是因为每个测试都按照自己的承诺运行吗?当它在上述承诺中为 运行 时,它无法登录到控制台?还是因为我在调用new ClassA()之前没有清除现有的ClassA实例?
======编辑======
使用断点后我发现调用了构造函数,但它没有写入控制台。但是抛出永远不会发生,redis 是如何工作的;如果它有错误,一个事件被发送到名称为 "error" 的 redis 服务器,这在 运行 测试时不会被触发,如何等待它触发?
我通过制作 redisSub public 并调用 process.exit(); 解决了这个问题;当连接失败时,在单元测试中我监视 process.exit() 并检查它是否已被调用。
这是测试代码:
describe('Socket.io redis testing', () => {
test('should fail due to invalid serverIP', () => {
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
constants.config.redisServerIP = "127.312.12.1";
classA.stopServer();
classA = null;
classA = new ClassA();
classA.redisSub.on('error', () => {
expect(mockExit).toHaveBeenCalledWith(1);
});
mockExit.mockRestore();
});
虽然在 ClassA 中使用事件也可以,但我认为这不是最优雅的解决方案。
问题
在单元测试中创建新的 class 实例不会触发构造函数。
详情
我正在尝试测试在给出错误的服务器 IP 时是否抛出错误,但是当我尝试创建一个应该抛出错误的 class 的新实例时它不起作用。
我要测试的 class 是:
export class ClassA {
private readonly _redisServerIP = config.redisServerIP;
private readonly _redisServerPort = config.redisServerPort;
constructor() {
console.log(this._redisServerIP);
this.configure();
}
private configure(): void {
this._redisSub = redis.createClient({host: this._redisServerIP, port: this._redisServerPort});
this._redisSub.on('error', (error) => {
if (error.code === "ECONNREFUSED") {
this._logger.error('Could not create a redisSub, is the redis server running?');
}
throw new Error('Something bad happened');
});
}
}
这是我的测试代码:
import * as constants from '../src/config/config';
let socket;
let classA;
let httpServerAddr;
beforeAll((done) => {
classA = new ClassA();
httpServerAddr = classA.getServerIp();
done();
});
afterAll((done) => {
done();
});
beforeEach((done) => {
});
afterEach((done) => {
done();
});
describe('Socket.io redis testing', () => {
test('should fail due to invalid serverIP', () => {
constants.config.redisServerIP = "0.0.0.0";
classA = null;
expect(() => {
classA = new ClassA();
}).toThrow();
});
});
我在我的节点控制台中只看到一次服务器 ip,由于以下错误导致测试失败:
expect(function).toThrow(undefined)
Expected the function to throw an error.
But it didn't throw anything.
这是因为每个测试都按照自己的承诺运行吗?当它在上述承诺中为 运行 时,它无法登录到控制台?还是因为我在调用new ClassA()之前没有清除现有的ClassA实例?
======编辑======
使用断点后我发现调用了构造函数,但它没有写入控制台。但是抛出永远不会发生,redis 是如何工作的;如果它有错误,一个事件被发送到名称为 "error" 的 redis 服务器,这在 运行 测试时不会被触发,如何等待它触发?
我通过制作 redisSub public 并调用 process.exit(); 解决了这个问题;当连接失败时,在单元测试中我监视 process.exit() 并检查它是否已被调用。
这是测试代码:
describe('Socket.io redis testing', () => {
test('should fail due to invalid serverIP', () => {
const mockExit = jest.spyOn(process, 'exit').mockImplementation(() => {});
constants.config.redisServerIP = "127.312.12.1";
classA.stopServer();
classA = null;
classA = new ClassA();
classA.redisSub.on('error', () => {
expect(mockExit).toHaveBeenCalledWith(1);
});
mockExit.mockRestore();
});
虽然在 ClassA 中使用事件也可以,但我认为这不是最优雅的解决方案。