Explain how to test function logic, service integrations, and trigger contracts. Show why each level is important in a serverless delivery pipeline.
Unit, integration, and contract testing play different roles in a serverless delivery pipeline, and confusing them leads to fragile systems. Unit tests protect function logic and edge cases inside one bounded handler. Integration tests prove that the function can actually talk to real services and triggers. Contract tests protect the schemas and assumptions that let different parts of the system communicate safely.
In serverless systems, contract testing matters more than many teams expect because functions often depend on event structure, queue metadata, IAM configuration, and managed-service behavior that are easy to change accidentally. A passing unit test does not prove that an event producer and consumer still agree.
flowchart LR
A["Unit tests"] --> B["Integration tests"]
B --> C["Contract tests"]
C --> D["Deployment pipeline"]
What to notice:
Unit tests are strongest for:
They should not require cloud resources or long setup. The function handler should be structured so the core logic can be tested with ordinary inputs and mocks.
1export function normalizeOrderAmount(rawAmount: number) {
2 if (rawAmount < 0) {
3 throw new Error("amount must be non-negative");
4 }
5 return Math.round(rawAmount * 100);
6}
Integration tests answer questions unit tests cannot:
This is especially important in serverless systems because the boundary between application code and managed services is large.
Contract tests are often the missing layer. They verify that:
1event_contract:
2 name: invoice.generated
3 required_fields:
4 - invoiceId
5 - tenantId
6 - totalAmount
7 allowed_versions:
8 - v1
A healthy delivery pipeline usually has:
The anti-pattern is to rely on unit tests alone because they are faster. Fast tests are useful, but false confidence is expensive.
A queue consumer passes unit tests, but a producer change later breaks production because one field was renamed in the event payload. What testing layer was missing?
The stronger answer is contract testing between producer and consumer. Integration tests might also have caught it, but the main gap was that the shared event boundary had no explicit automated compatibility check.