在玩笑测试中调用new class()之后,没有创建新的类实例

时间:2018-11-29 13:13:02

标签: typescript unit-testing testing jestjs node-redis

问题

在单元测试中创建新的类实例不会触发构造函数。


详细信息

我正在尝试测试在给定错误服务器IP的情况下是否引发了错误,但是当我尝试创建应该引发该错误的类的新实例时,则不起作用。

我要测试的课程是:

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的现有实例?

====== EDIT ======

使用断点后,我发现调用了构造函数,但是它没有写入控制台。但是抛出永远不会发生,Redis的工作原理是这样。如果有错误,则将事件发送到名称为“ error”的redis服务器,在运行测试时不会触发该事件,请问如何等待触发该事件?

1 个答案:

答案 0 :(得分:0)

我已通过将redisSub公开并调用process.exit()来解决了这个问题。当连接失败时,在单元测试中,我spyOn 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中使用事件也可以,但我认为这不是最优雅的解决方案。