Skip to content

Commit

Permalink
fix: add test for race condition
Browse files Browse the repository at this point in the history
Add test for race condition
  • Loading branch information
ttshivers committed Jan 16, 2024
1 parent 0e42f93 commit e0f9974
Showing 1 changed file with 90 additions and 0 deletions.
90 changes: 90 additions & 0 deletions integration/rabbitmq/e2e/configuration.e2e-spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ const logger = new ConsoleLogger('Custom logger');
const nonExistingExchange = 'non-existing-exchange';
const nonExistingQueue = 'non-existing-queue';

const testRoutingKey = 'test';

class RabbitConfig {
createModuleConfig(): RabbitMQConfig {
return {
Expand All @@ -33,6 +35,7 @@ describe('Module Configuration', () => {

afterEach(async () => {
jest.clearAllMocks();
jest.restoreAllMocks();
await app?.close();
});

Expand Down Expand Up @@ -429,6 +432,93 @@ describe('Module Configuration', () => {
// Clear non-existing exchange
await amqpConnection.channel.deleteExchange(nonExistingExchange);
});

it('should create an exchange successfully if `createExchangeIfNotExists` is true before binding queues', async () => {
const originalConnect = amqplib.connect;

// Spy on the internals of amqplib to be able to introduce delays in some functions
// to expose race conditions or unawaited promises
const connectSpy = jest
.spyOn(amqplib, 'connect')
.mockImplementation((...args) => {
const result = originalConnect(...args);
result.then((conn) => {
const originalCreateConfirmChannel = conn.createConfirmChannel;
jest
.spyOn(conn, 'createConfirmChannel')
.mockImplementation(function (...args) {
const result = originalCreateConfirmChannel.apply(this, args);
result.then((channel) => {
const bindQueueSpy = jest.spyOn(channel, 'bindQueue');

const originalAssertExchange = channel.assertExchange;
jest
.spyOn(channel, 'assertExchange')
.mockImplementation(function (...args) {
// Delay for a long time to ensure queues are bound after exchanges are asserted
return new Promise((r) => setTimeout(r, 500)).then(
() => {
const result = originalAssertExchange.apply(
this,
args,
);
result.then(() => {
expect(bindQueueSpy).not.toBeCalled();
});
return result;
},
) as any;
});
});
return result;
});
});
return result;
});

app = await Test.createTestingModule({
imports: [
RabbitMQModule.forRootAsync(RabbitMQModule, {
useFactory: async () => {
return {
exchanges: [
{
name: nonExistingExchange,
type: 'topic',
createExchangeIfNotExists: true,
},
],
queues: [
{
name: nonExistingQueue,
exchange: nonExistingExchange,
routingKey: testRoutingKey,
},
],
uri,
connectionInitOptions: {
wait: true,
reject: true,
timeout: 10000,
},
};
},
}),
],
}).compile();

const amqpConnection = app.get<AmqpConnection>(AmqpConnection);
expect(app).toBeDefined();

expect(connectSpy).toHaveBeenCalledTimes(1);
expect(connectSpy).toHaveBeenCalledWith(amqplibUri, undefined);

await app.init();
expect(
await amqpConnection.channel.checkExchange(nonExistingExchange),
).toBeDefined();
await app.close();
});
});
});
});

0 comments on commit e0f9974

Please sign in to comment.