m-radzikowski/aws-sdk-client-mock

SQSClient received matching "DeleteMessageCommand" 0 times, after "SendMessageCommand" is run

Closed this issue · 1 comments

Checklist

  • I have read Caveats documentation and didn't find a solution for this problem there.

Bug description

I'm running into a problem that doesn't make sense to me:

Expected SQSClient to receive "DeleteMessageCommand" with {"QueueUrl": "https://sqs.us-west-2.amazonaws.com/***", "ReceiptHandle": "***"}                                                                          
    SQSClient received matching "DeleteMessageCommand" 0 times 

I'm writing tests for a long polling loop. Inside the loop I call (and await) a function, like sendToQueue in the reproduction, that sends the message to another queue, and deletes it from the current queue.

I don't understand why DeleteMessageCommand is not being shown as being called by the test runner.

If I remove the code that performs the "SendMessageCommand", or move the code to "DeleteMessageCommand" before "SendMessageCommand", then I see that "DeleteMessageCommand" was called. In the case I run "DeleteMessageCommand" before "SendMessageCommand," then it shows "SendMessageCommand" was not called.

It seems like the test cannot recognize both as being called, however when I run the function in production against the actual queue it appears the messages are both sent and deleted properly.

*Sorry I'm new to AWS SQS, writing tests, and creating github issues, so please have mercy. :)

Reproduction

it("forwards valid message to myqueue", async () => {
  sqsMock
    .on(ReceiveMessageCommand)
    .resolves(mockReceiveMessageValid)
    .on(SendMessageCommand)
    .resolves(mockSendMessageResult)
    .on(DeleteMessageCommand)
    .resolves({});

  await expect(myPollFunction()).resolves.not.toThrow();

  expect(sqsMock).toHaveReceivedCommandWith(SendMessageCommand, {
    QueueUrl: OTHER_QUEUE_URL
    MessageBody: mockBody,
  });

  expect(sqsMock).toHaveReceivedCommandWith(DeleteMessageCommand, {
    QueueUrl: CURRENT_QUEUE_URL
    ReceiptHandle: mockReceiptHandle,
  });
});
export default async function sendToQueue({
  MessageBody,
  ReceiptHandle,
}: {
  MessageBody: string;
  ReceiptHandle: string;
}) {
  try {
    const sendParams = {
      QueueUrl: OTHER_QUEUE_URL, 
      MessageBody: MessageBody,
    };

    const sendCommand = new SendMessageCommand(sendParams);
    const sendResponse = await sqs.send(sendCommand);

    const deleteParams = {
      QueueUrl: CURRENT_QUEUE_URL, 
      ReceiptHandle: ReceiptHandle, 
    };

    const deleteCommand = new DeleteMessageCommand(deleteParams);
    const deleteResponse = await sqs.send(deleteCommand);
  } catch (err) {
    console.error("Failed to forward and delete", err);
  }
}

Environment

  • Node version: v18.18.2
  • Testing lib and version: "jest": "^29.7.0",
  • Typescript version: "typescript": "^5.3.3",
  • AWS SDK v3 Client mock version:
    • "aws-sdk-client-mock": "^3.0.1",
    • "aws-sdk-client-mock-jest": "^3.0.1",
  • AWS JS SDK libs and versions:
    • "@aws-sdk/client-sqs": "^3.501.0",

My bad.

I discovered the the await was running inside of a .forEach and the test was ending before each .forEach iteration was completed.