diff --git a/lib/controller.ts b/lib/controller.ts index 2dbf197d9..7a0b64bea 100644 --- a/lib/controller.ts +++ b/lib/controller.ts @@ -137,7 +137,14 @@ class Controller { } // MQTT - await this.mqtt.connect(); + try { + await this.mqtt.connect(); + } catch (error) { + logger.error(`MQTT failed to connect: ${error.message}`); + logger.error('Exiting...'); + await this.zigbee.stop(); + this.exitCallback(1); + } // Send all cached states. if (settings.get().advanced.cache_state_send_on_startup && settings.get().advanced.cache_state) { diff --git a/lib/mqtt.ts b/lib/mqtt.ts index 313f77c9c..8442348da 100644 --- a/lib/mqtt.ts +++ b/lib/mqtt.ts @@ -67,7 +67,7 @@ export default class MQTT { options.rejectUnauthorized = false; } - return new Promise((resolve) => { + return new Promise((resolve, reject) => { this.client = mqtt.connect(mqttSettings.server, options); const onConnect = this.onConnect; @@ -76,6 +76,7 @@ export default class MQTT { resolve(); }); + this.client.on('error', (err) => reject(err)); this.client.on('message', this.onMessage); }); } diff --git a/test/controller.test.js b/test/controller.test.js index 0af5975ec..d8177754e 100644 --- a/test/controller.test.js +++ b/test/controller.test.js @@ -25,6 +25,7 @@ describe('Controller', () => { }); beforeEach(() => { + MQTT.restoreOnMock(); zigbeeHerdsman.returnDevices.splice(0); mockExit = jest.fn(); controller = new Controller(jest.fn(), mockExit); @@ -209,6 +210,17 @@ describe('Controller', () => { expect(mockExit).toHaveBeenCalledTimes(1); }); + it('Start controller fails due to MQTT', async () => { + MQTT.on.mockImplementation((type, handler) => { + if (type === 'error') handler({message: 'addr not found'}); + }); + await controller.start(); + await flushPromises(); + expect(logger.error).toHaveBeenCalledWith('MQTT failed to connect: addr not found'); + expect(mockExit).toHaveBeenCalledTimes(1); + expect(mockExit).toHaveBeenCalledWith(1); + }); + it('Start controller with permit join true', async () => { settings.set(['permit_join'], false); await controller.start(); diff --git a/test/stub/mqtt.js b/test/stub/mqtt.js index 4ecf5e9ce..46ff57b54 100644 --- a/test/stub/mqtt.js +++ b/test/stub/mqtt.js @@ -5,13 +5,7 @@ const mock = { end: jest.fn(), subscribe: jest.fn(), reconnecting: false, - on: (type, handler) => { - if (type === 'connect') { - handler(); - } - - events[type] = handler - }, + on: jest.fn(), }; const mockConnect = jest.fn().mockReturnValue(mock); @@ -20,6 +14,18 @@ jest.mock('mqtt', () => { return {connect: mockConnect}; }); +const restoreOnMock = () => { + mock.on.mockImplementation((type, handler) => { + if (type === 'connect') { + handler(); + } + + events[type] = handler + }); +} + +restoreOnMock(); + module.exports = { - events, ...mock, connect: mockConnect, mock, + events, ...mock, connect: mockConnect, mock, restoreOnMock }; \ No newline at end of file