I'm creating a façade for the nats streaming lib as follows:
import nats, { Message, Stan, Subscription, SubscriptionOptions } from 'node-nats-streaming'
class NatsHelper {
private client: Stan | null = null
public connect(url: string, clusterID: string, clientID: string, listener: (...args: any[]) => void, verboseConnection: boolean = true): void {
const clientIDString = `${clientID}-${randomBytes(4).toString('hex')}`
if (verboseConnection) {
console.log(`Connecting to NATS cluster '${clusterID}' with clientID '${clientIDString}' on url '${url}'`)
}
const connectionAttempt = nats.connect(
clusterID,
clientIDString,
{
url
}
)
const setupConnection = (...args: any[]): void => {
this.client = connectionAttempt
this.client.on('close', (): void => {
if (verboseConnection) {
console.log(`Connection with NATS cluster '${clusterID}' with clientID '${clientIDString}' on url '${url}' was closed`)
}
this.client = null
process.exit()
})
process.on('SIGINT', () => this.client?.close())
process.on('SIGTERM', () => this.client?.close())
if (verboseConnection) {
console.log(`Connected to NATS cluster '${clusterID}' with clientID '${clientIDString}' on url '${url}' successfuly`)
}
listener(...args)
}
connectionAttempt.on('connect', setupConnection)
}
}
It happens though that I'm not able to test if the provided listener function is called, because it relies on the Stan 'connect' event to happen and jest finishes the test before it happens.
How can I make jest wait for this event to happen, and then executes the expect function?
You have overcomplicated this. It's perfectly possible to write the test for the original code without modifying it by mocking out the library using jest.mock()
, and injecting mock implementations for your on method. Like this:
import nats from "node-nats-streaming";
import { mock } from "jest-mock-extended";
import { NatsHelper } from "./nats";
jest.mock("node-nats-streaming");
describe("NatsHelper", () => {
it("calls listener on connectEvent", () => {
const client = mock<nats.Stan>();
client.on.mockImplementation((name, callback) => {
if (name !== "close") {
callback();
}
return client;
});
jest.mocked(nats).connect.mockReturnValue(client);
const connector = new NatsHelper();
const listener = jest.fn();
connector.connect("foo", "foo", "foo", listener);
expect(listener).toHaveBeenCalled();
});
});