Skip to content

Commit 13474a0

Browse files
committed
Imrprove testing coverage of the orchestration suite
1 parent 4e73794 commit 13474a0

4 files changed

Lines changed: 118 additions & 35 deletions

File tree

packages/postDatedLambda/tests/testDatabaseClient.test.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ import * as dynamo from "@aws-sdk/client-dynamodb"
99

1010
import {Logger} from "@aws-lambda-powertools/logger"
1111

12-
import {createMockPostModifiedDataItem} from "./testUtils"
12+
import {createMockPostModifiedDataItem} from "./testUtils.test"
1313

1414
// Uses unstable jest method to enable mocking while using ESM. To be replaced in future.
1515
export function mockDynamoDBClient() {

packages/postDatedLambda/tests/testOrchestration.test.ts

Lines changed: 101 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ jest.unstable_mockModule("../src/sqs", () => {
3333

3434
import {Logger} from "@aws-lambda-powertools/logger"
3535

36-
import {createMockPostModifiedDataItem} from "./testUtils"
36+
import {createMockPostModifiedDataItem} from "./testUtils.test"
3737
import {BatchProcessingResult, PostDatedSQSMessage} from "../src/types"
3838

3939
// Import the orchestration module after mocking dependencies
@@ -43,6 +43,10 @@ const logger = new Logger({serviceName: "postDatedLambdaTEST"})
4343

4444
describe("orchestration", () => {
4545
describe("processMessages", () => {
46+
beforeEach(() => {
47+
jest.clearAllMocks()
48+
})
49+
4650
it("should process messages and categorize them correctly", async () => {
4751
const mockMessages: Array<PostDatedSQSMessage> = [
4852
{MessageId: "1", Body: "Message 1", prescriptionData: createMockPostModifiedDataItem({})},
@@ -69,6 +73,51 @@ describe("orchestration", () => {
6973

7074
expect(result.maturedPrescriptionUpdates).toHaveLength(0)
7175
expect(result.immaturePrescriptionUpdates).toHaveLength(0)
76+
expect(mockEnrichMessagesWithExistingRecords).not.toHaveBeenCalled()
77+
})
78+
79+
it("should log errors and mark messages immature when processing throws", async () => {
80+
const mockMessages: Array<PostDatedSQSMessage> = [
81+
{MessageId: "1", Body: "Message 1", prescriptionData: createMockPostModifiedDataItem({})},
82+
{MessageId: "2", Body: "Message 2", prescriptionData: createMockPostModifiedDataItem({})}
83+
]
84+
85+
mockEnrichMessagesWithExistingRecords.mockReturnValueOnce(mockMessages)
86+
mockProcessMessage
87+
.mockReturnValueOnce(true)
88+
.mockImplementationOnce(async () => {
89+
throw new Error("processing failed")
90+
})
91+
92+
const errorSpy = jest.spyOn(logger, "error")
93+
const result = await processMessages(mockMessages, logger)
94+
95+
expect(result.maturedPrescriptionUpdates).toHaveLength(1)
96+
expect(result.immaturePrescriptionUpdates).toHaveLength(1)
97+
expect(result.immaturePrescriptionUpdates[0].MessageId).toBe("2")
98+
expect(errorSpy).toHaveBeenCalledWith(
99+
"Error processing message",
100+
expect.objectContaining({messageId: "2"})
101+
)
102+
errorSpy.mockRestore()
103+
})
104+
105+
it("should pass enriched records into processMessage", async () => {
106+
const mockMessages: Array<PostDatedSQSMessage> = [
107+
{MessageId: "1", Body: "Message 1", prescriptionData: createMockPostModifiedDataItem({})}
108+
]
109+
110+
const enrichedMessage = {
111+
...mockMessages[0],
112+
existingRecords: [{prescriptionId: "abc"}]
113+
}
114+
115+
mockEnrichMessagesWithExistingRecords.mockReturnValueOnce([enrichedMessage])
116+
mockProcessMessage.mockReturnValue(true)
117+
118+
await processMessages(mockMessages, logger)
119+
120+
expect(mockProcessMessage).toHaveBeenCalledWith(logger, enrichedMessage)
72121
})
73122
})
74123

@@ -138,5 +187,56 @@ describe("orchestration", () => {
138187
expect(mockReportQueueStatus).toHaveBeenCalled()
139188
jest.useRealTimers()
140189
})
190+
191+
it("should continue processing batches until message count drops below threshold", async () => {
192+
const createBatch = (ids: Array<string>) =>
193+
ids.map((id) => ({
194+
MessageId: id,
195+
Body: `Message ${id}`,
196+
prescriptionData: createMockPostModifiedDataItem({})
197+
}))
198+
199+
const batch1 = createBatch(["1", "2", "3"])
200+
const batch2 = createBatch(["4", "5", "6"])
201+
const batch3 = createBatch(["7"])
202+
203+
const enrich = (messages: Array<PostDatedSQSMessage>) =>
204+
messages.map((message) => ({
205+
...message,
206+
existingRecords: []
207+
}))
208+
209+
mockReceivePostDatedSQSMessages
210+
.mockReturnValueOnce(batch1)
211+
.mockReturnValueOnce(batch2)
212+
.mockReturnValueOnce(batch3)
213+
mockEnrichMessagesWithExistingRecords
214+
.mockReturnValueOnce(enrich(batch1))
215+
.mockReturnValueOnce(enrich(batch2))
216+
.mockReturnValueOnce(enrich(batch3))
217+
mockProcessMessage.mockReturnValue(true)
218+
219+
await processPostDatedQueue(logger)
220+
221+
expect(mockReceivePostDatedSQSMessages).toHaveBeenCalledTimes(3)
222+
expect(mockHandleProcessedMessages).toHaveBeenCalledTimes(3)
223+
expect(mockReportQueueStatus).not.toHaveBeenCalled()
224+
const totalMessages = batch1.length + batch2.length + batch3.length
225+
expect(mockProcessMessage).toHaveBeenCalledTimes(totalMessages)
226+
})
227+
228+
it("should treat empty receives as drained batches", async () => {
229+
mockReceivePostDatedSQSMessages.mockReturnValueOnce([])
230+
231+
await processPostDatedQueue(logger)
232+
233+
expect(mockEnrichMessagesWithExistingRecords).not.toHaveBeenCalled()
234+
expect(mockProcessMessage).not.toHaveBeenCalled()
235+
expect(mockHandleProcessedMessages).toHaveBeenCalledTimes(1)
236+
const [result] = mockHandleProcessedMessages.mock.calls[0] as [BatchProcessingResult]
237+
expect(result.maturedPrescriptionUpdates).toHaveLength(0)
238+
expect(result.immaturePrescriptionUpdates).toHaveLength(0)
239+
expect(mockReportQueueStatus).not.toHaveBeenCalled()
240+
})
141241
})
142242
})
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import {PostDatedNotifyDataItem} from "packages/common/commonTypes/lib/src"
2+
3+
export function createMockPostModifiedDataItem(overrides: Partial<PostDatedNotifyDataItem>): PostDatedNotifyDataItem {
4+
return {
5+
LastModified: "2023-01-02T00:00:00Z",
6+
LineItemID: "spamandeggs",
7+
PatientNHSNumber: "0123456789",
8+
PharmacyODSCode: "ABC123",
9+
PrescriptionID: "abcdef-ghijkl-mnopqr",
10+
RequestID: "x-request-id",
11+
Status: "ready to collect",
12+
TaskID: "mnopqr-ghijkl-abcdef",
13+
PostDatedLastModifiedSetAt: "Changed dosage instructions",
14+
...overrides
15+
}
16+
}

packages/postDatedLambda/tests/testUtils.ts

Lines changed: 0 additions & 33 deletions
This file was deleted.

0 commit comments

Comments
 (0)