Natural Language Testing
Prompt: “Test payment service integration with timeout handling and rollback scenarios”
Output: Complete test suite with service mocks and error injection
PRD: Comprehensive Integration Testing System
Requirements: Validate service interactions, API contracts, database transactions, and message queue communications with 95%+ reliability using AI-generated test scenarios.
Plan: Use Cursor IDE and Claude Code with specialized MCP servers (Database, API testing, Message Queue) to create comprehensive integration test suites that catch interaction bugs and ensure system reliability.
Todo:
Integration testing moves beyond simple API calls to intelligent validation of complex system interactions. AI helps you discover hidden dependencies, generate realistic test scenarios, and maintain tests as your architecture evolves.
Natural Language Testing
Prompt: “Test payment service integration with timeout handling and rollback scenarios”
Output: Complete test suite with service mocks and error injection
Contract Intelligence
AI analyzes API schemas and generates consumer-driven contract tests automatically
Data Flow Validation
Trace data consistency across services, databases, and message queues
Performance Integration
Monitor response times, throughput, and resource usage across service boundaries
Scenario: Testing a complex e-commerce order processing system with multiple service dependencies.
# PRD: E-commerce Order Processing Integration Tests# Requirements: Validate complete order flow with service interactions
"Analyze our microservices architecture and create integration tests:
Services involved:- Order Service (orchestrator)- User Service (authentication)- Inventory Service (stock management)- Payment Service (billing)- Shipping Service (fulfillment)- Notification Service (communications)
Test scenarios needed:1. Happy path: Complete order processing2. Inventory shortage: Rollback handling3. Payment failure: Order cancellation4. Shipping unavailable: Status updates5. Service timeout: Circuit breaker activation6. Partial failures: Compensation patterns
Requirements:- Contract testing for all service boundaries- Transaction consistency validation- Performance under load- Error propagation testing- Monitoring and alerting validation"
// AI generates comprehensive microservices integration testsdescribe('Order Processing Integration', () => { let testEnvironment: TestEnvironment; let services: ServiceMesh;
beforeAll(async () => { // AI sets up complete test environment testEnvironment = await createIntegrationTestEnvironment({ services: ['order', 'user', 'inventory', 'payment', 'shipping', 'notification'], databases: ['orders', 'users', 'inventory'], messageQueues: ['order-events', 'notifications'], externalMocks: ['stripe', 'fedex-api'] });
services = testEnvironment.services; });
describe('Complete Order Flow', () => { it('processes order with all services successfully', async () => { // Arrange - AI creates realistic test data const user = await testEnvironment.createTestUser({ email: 'customer@example.com', paymentMethods: [{ type: 'card', last4: '4242' }] });
const products = await testEnvironment.seedInventory([ { id: 'prod-1', stock: 10, price: 29.99 }, { id: 'prod-2', stock: 5, price: 49.99 } ]);
const orderRequest = { userId: user.id, items: [ { productId: 'prod-1', quantity: 2 }, { productId: 'prod-2', quantity: 1 } ], shippingAddress: AddressFactory.build(), paymentMethod: user.paymentMethods[0].id };
// Act - Submit order and trace through services const traceId = generateTraceId(); const orderResponse = await services.order.createOrder(orderRequest, { headers: { 'X-Trace-Id': traceId } });
// Wait for async processing to complete await testEnvironment.waitForOrderCompletion(orderResponse.id, { timeout: 30000, expectedStatus: 'confirmed' });
// Assert - Validate end-to-end flow const finalOrder = await services.order.getOrder(orderResponse.id); expect(finalOrder.status).toBe('confirmed'); expect(finalOrder.payment.status).toBe('charged'); expect(finalOrder.shipping.status).toBe('pending');
// Verify inventory was decremented const updatedInventory = await services.inventory.getStock(['prod-1', 'prod-2']); expect(updatedInventory['prod-1']).toBe(8); // 10 - 2 expect(updatedInventory['prod-2']).toBe(4); // 5 - 1
// Verify notification was sent const notifications = await testEnvironment.getNotifications(user.id); expect(notifications).toContainEqual( expect.objectContaining({ type: 'order_confirmed', orderId: orderResponse.id }) ); });
it('handles inventory shortage with proper rollback', async () => { // AI generates failure scenario tests const user = await testEnvironment.createTestUser();
// Set insufficient inventory await testEnvironment.seedInventory([ { id: 'prod-low', stock: 1, price: 99.99 } ]);
const orderRequest = { userId: user.id, items: [{ productId: 'prod-low', quantity: 5 }] // More than available };
const orderResponse = await services.order.createOrder(orderRequest);
// Wait for processing to complete await testEnvironment.waitForOrderCompletion(orderResponse.id, { expectedStatus: 'cancelled' });
// Verify rollback occurred const cancelledOrder = await services.order.getOrder(orderResponse.id); expect(cancelledOrder.status).toBe('cancelled'); expect(cancelledOrder.cancellationReason).toBe('insufficient_inventory');
// Verify no payment was charged expect(cancelledOrder.payment.status).toBe('not_attempted');
// Verify inventory unchanged const inventory = await services.inventory.getStock('prod-low'); expect(inventory).toBe(1); }); });});
Scenario: Ensuring API compatibility between services as they evolve independently.
# PRD: Consumer-Driven Contract Testing# Plan: Use Pact.js with AI-generated contract scenarios
"Create contract tests for our service ecosystem:
Service relationships:- OrderService (consumer) → UserService (provider)- OrderService (consumer) → PaymentService (provider)- NotificationService (consumer) → UserService (provider)- InventoryService (consumer) → ProductService (provider)
For each contract:1. Generate realistic request/response scenarios2. Include error conditions and edge cases3. Test schema evolution compatibility4. Create provider verification tests5. Set up contract publishing workflow6. Add breaking change detection
Focus on:- Authentication token validation- Data format consistency- Error response standards- Performance expectations"
// AI generates comprehensive contract testing suiteimport { Pact } from '@pact-foundation/pact';import { OrderService } from '../OrderService';
describe('OrderService Contract Tests', () => { const provider = new Pact({ consumer: 'OrderService', provider: 'UserService', port: 8080, log: path.resolve(process.cwd(), 'logs', 'pact.log'), dir: path.resolve(process.cwd(), 'pacts'), logLevel: 'INFO' });
beforeAll(() => provider.setup()); afterEach(() => provider.verify()); afterAll(() => provider.finalize());
describe('User Service Interactions', () => { it('retrieves user for valid order creation', async () => { // AI generates realistic contract interactions await provider.addInteraction({ state: 'user with id 12345 exists and is active', uponReceiving: 'a request for user details for order creation', withRequest: { method: 'GET', path: '/api/v1/users/12345', headers: { 'Authorization': like('Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...'), 'Accept': 'application/json', 'X-Request-ID': like('req-12345') } }, willRespondWith: { status: 200, headers: { 'Content-Type': 'application/json', 'X-Response-Time': like('45ms') }, body: { id: '12345', email: like('user@example.com'), name: like('John Doe'), status: 'active', paymentMethods: eachLike({ id: like('pm_12345'), type: like('card'), last4: like('4242'), brand: like('visa') }), addresses: eachLike({ id: like('addr_67890'), type: like('shipping'), street: like('123 Main St'), city: like('San Francisco'), country: like('US'), postalCode: like('94105') }), preferences: { currency: like('USD'), language: like('en'), notifications: { email: like(true), sms: like(false) } } } } });
// Test the consumer code const orderService = new OrderService({ userServiceUrl: provider.mockService.baseUrl, apiKey: 'test-key' });
const user = await orderService.getUserForOrder('12345');
// AI adds comprehensive assertions expect(user).toMatchObject({ id: '12345', email: expect.stringMatching(/^[^\s@]+@[^\s@]+\.[^\s@]+$/), status: 'active', paymentMethods: expect.arrayContaining([ expect.objectContaining({ type: expect.stringMatching(/^(card|bank|paypal)$/) }) ]) }); });
it('handles user not found scenario', async () => { // AI generates error scenario contracts await provider.addInteraction({ state: 'user with id 99999 does not exist', uponReceiving: 'a request for non-existent user', withRequest: { method: 'GET', path: '/api/v1/users/99999', headers: { 'Authorization': like('Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...'), 'Accept': 'application/json' } }, willRespondWith: { status: 404, headers: { 'Content-Type': 'application/json' }, body: { error: { code: 'USER_NOT_FOUND', message: 'User with id 99999 not found', timestamp: like('2024-01-01T12:00:00Z'), requestId: like('req-error-123') } } } });
const orderService = new OrderService({ userServiceUrl: provider.mockService.baseUrl });
await expect(orderService.getUserForOrder('99999')) .rejects.toThrow('User with id 99999 not found'); }); });});
Scenario: Testing complex database transactions and data consistency across multiple tables and services.
// AI-generated database integration testdescribe('Order Processing Transaction', () => { let db: Database; let orderService: OrderService; let inventoryService: InventoryService;
beforeEach(async () => { db = await createTestDatabase(); orderService = new OrderService(db); inventoryService = new InventoryService(db); });
it('should maintain consistency during order creation', async () => { // AI generates test with proper transaction handling const productId = 'prod-123'; const quantity = 5;
// Setup initial inventory await inventoryService.setStock(productId, 10);
// Start transaction const transaction = await db.beginTransaction();
try { // Create order const order = await orderService.createOrder({ productId, quantity, userId: 'user-123' }, transaction);
// Update inventory await inventoryService.decrementStock( productId, quantity, transaction );
await transaction.commit();
// Verify consistency const finalStock = await inventoryService.getStock(productId); expect(finalStock).toBe(5);
const savedOrder = await orderService.getOrder(order.id); expect(savedOrder.status).toBe('confirmed'); } catch (error) { await transaction.rollback(); throw error; } });
// AI adds rollback scenario it('should rollback on insufficient inventory', async () => { const productId = 'prod-456'; await inventoryService.setStock(productId, 3);
await expect(async () => { await db.transaction(async (trx) => { await orderService.createOrder({ productId, quantity: 5, userId: 'user-789' }, trx);
await inventoryService.decrementStock(productId, 5, trx); }); }).rejects.toThrow('Insufficient inventory');
// Verify no changes were made const stock = await inventoryService.getStock(productId); expect(stock).toBe(3); });});
// AI-generated migration testdescribe('Database Migration Integration', () => { it('should migrate data correctly', async () => { // Setup old schema const oldDb = await createDatabase('v1_schema'); await seedTestData(oldDb);
// Run migration await runMigration('v1_to_v2');
// Verify data integrity const newDb = await createDatabase('v2_schema');
// AI generates comprehensive checks const users = await newDb.query('SELECT * FROM users'); expect(users).toHaveLength(100); expect(users[0]).toHaveProperty('created_at'); // New field
const orders = await newDb.query('SELECT * FROM orders'); expect(orders.every(o => o.user_id)).toBe(true);
// Verify relationships maintained const userOrders = await newDb.query(` SELECT u.id, COUNT(o.id) as order_count FROM users u LEFT JOIN orders o ON u.id = o.user_id GROUP BY u.id `); expect(userOrders).toMatchSnapshot(); });});
Scenario: Validating event-driven communication between microservices with reliable message delivery.
// AI-generated message queue integration testdescribe('Event-Driven Order Processing', () => { let messageQueue: MessageQueue; let orderService: OrderService; let paymentService: PaymentService; let shippingService: ShippingService;
beforeEach(async () => { messageQueue = await createTestMessageQueue();
// AI sets up service connections orderService = new OrderService(messageQueue); paymentService = new PaymentService(messageQueue); shippingService = new ShippingService(messageQueue);
// Start services await Promise.all([ orderService.start(), paymentService.start(), shippingService.start() ]); });
it('should process order through entire pipeline', async () => { // AI creates comprehensive event flow test const orderId = 'order-123'; const orderCreatedPromise = waitForEvent( messageQueue, 'order.created' ); const paymentProcessedPromise = waitForEvent( messageQueue, 'payment.processed' ); const orderShippedPromise = waitForEvent( messageQueue, 'order.shipped' );
// Trigger order creation await orderService.createOrder({ id: orderId, items: [{ productId: 'prod-1', quantity: 2 }], total: 99.99 });
// Verify event chain const orderCreatedEvent = await orderCreatedPromise; expect(orderCreatedEvent.data.orderId).toBe(orderId);
const paymentEvent = await paymentProcessedPromise; expect(paymentEvent.data.orderId).toBe(orderId); expect(paymentEvent.data.status).toBe('success');
const shippingEvent = await orderShippedPromise; expect(shippingEvent.data.orderId).toBe(orderId); expect(shippingEvent.data.trackingNumber).toBeDefined(); });
// AI adds error propagation test it('should handle payment failure gracefully', async () => { // Setup payment service to fail paymentService.mockPaymentGateway.failNext();
const orderFailedPromise = waitForEvent( messageQueue, 'order.failed' );
await orderService.createOrder({ id: 'order-fail-123', total: 999.99 });
const failureEvent = await orderFailedPromise; expect(failureEvent.data.reason).toBe('payment_failed'); expect(failureEvent.data.orderId).toBe('order-fail-123'); });});
Scenario: Testing complex GraphQL queries and mutations with nested data relationships.
// AI-generated GraphQL integration testdescribe('GraphQL API Integration', () => { let app: Application; let authService: AuthService; let dataLoader: DataLoader;
beforeAll(async () => { app = await createTestApp(); authService = app.get(AuthService); dataLoader = app.get(DataLoader); });
it('should resolve nested queries efficiently', async () => { // AI generates complex query test const query = ` query GetUserWithOrders($userId: ID!) { user(id: $userId) { id name email orders(limit: 10) { id total items { product { id name price } quantity } shippingAddress { street city country } } } } `;
const response = await request(app) .post('/graphql') .send({ query, variables: { userId: 'user-123' } }) .set('Authorization', 'Bearer test-token');
expect(response.body.errors).toBeUndefined(); expect(response.body.data.user).toMatchObject({ id: 'user-123', orders: expect.arrayContaining([ expect.objectContaining({ items: expect.arrayContaining([ expect.objectContaining({ product: expect.objectContaining({ id: expect.any(String), name: expect.any(String) }) }) ]) }) ]) });
// Verify no N+1 queries const queryCount = dataLoader.getQueryCount(); expect(queryCount).toBeLessThan(10); // Batched properly });});
Scenario: Using real production traffic patterns to validate integration behavior.
Traffic-Based Testing
// Using Keploy for real traffic testingimport { Keploy } from '@keploy/sdk';
describe('Production Traffic Replay', () => { let keploy: Keploy;
beforeAll(async () => { keploy = new Keploy({ mode: 'test', path: './keploy-tests' }); });
it('should handle captured production scenarios', async () => { // Keploy replays captured traffic const results = await keploy.runCapturedTests({ service: 'payment-service', environment: 'staging', coverageThreshold: 0.9 });
expect(results.passed).toBe(results.total); expect(results.coverage).toBeGreaterThan(0.9);
// Verify no regressions results.tests.forEach(test => { expect(test.responseMatches).toBe(true); expect(test.latency).toBeLessThan(test.baseline * 1.1); }); });});
// AI-generated distributed tracing testdescribe('Cross-Service Request Flow', () => { let tracer: Tracer; let services: ServiceMesh;
beforeEach(async () => { tracer = createTestTracer(); services = await deployTestServices(tracer); });
it('should maintain trace context across services', async () => { const traceId = generateTraceId();
// Make request with trace context const response = await services.gateway.request({ path: '/api/checkout', method: 'POST', headers: { 'X-Trace-Id': traceId }, body: { cartId: 'cart-123' } });
// Collect trace spans const spans = await tracer.getSpans(traceId);
// AI generates comprehensive trace validation expect(spans).toContainEqual( expect.objectContaining({ service: 'gateway', operation: 'checkout.start' }) );
expect(spans).toContainEqual( expect.objectContaining({ service: 'cart-service', operation: 'cart.validate' }) );
expect(spans).toContainEqual( expect.objectContaining({ service: 'payment-service', operation: 'payment.process' }) );
// Verify timing and dependencies const gatewaySpan = spans.find(s => s.service === 'gateway'); const paymentSpan = spans.find(s => s.service === 'payment-service');
expect(paymentSpan.parentId).toBe(gatewaySpan.spanId); expect(paymentSpan.startTime).toBeGreaterThan(gatewaySpan.startTime); });});
// AI-generated performance integration testdescribe('Service Integration Performance', () => { it('should handle concurrent requests across services', async () => { const loadTest = new LoadTest({ duration: '30s', vus: 100, // Virtual users thresholds: { 'http_req_duration': ['p(95) < 500'], // 95% under 500ms 'http_req_failed': ['rate < 0.01'], // Error rate under 1% } });
await loadTest.run(async (vu) => { // AI generates realistic user journey const userId = `user-${vu.id}`;
// Login const authResponse = await vu.post('/auth/login', { username: userId, password: 'test123' });
const token = authResponse.json('token');
// Browse products const products = await vu.get('/products', { headers: { Authorization: `Bearer ${token}` } });
// Add to cart const product = products.json('products[0]'); await vu.post('/cart/add', { productId: product.id, quantity: 1 });
// Checkout const order = await vu.post('/checkout', { paymentMethod: 'test-card' });
vu.check(order.status === 200, 'Checkout successful'); });
const results = await loadTest.getResults(); expect(results.checks.passes).toBeGreaterThan(0.99); expect(results.metrics.http_req_duration.p95).toBeLessThan(500); });});
Test Independence
// Each test manages its own test databeforeEach(async () => { testContext = await createIsolatedContext(); // Use unique IDs, separate databases, etc.});
Service Mocking
// Mock external dependencies consistentlyconst mockPaymentGateway = createMock({ responses: loadFromContract('payment-gateway-v2')});
Data Consistency
// Verify data consistency across servicesexpect(orderService.getOrder(id)) .toEqual(inventoryService.getOrderItems(id));
Error Propagation
// Test error handling across boundariesawait expectErrorChain() .from(paymentService) .through(orderService) .to(notificationService);
Real Traffic Capture & Replay
# Install and capture traffickeploy record -c "npm start"
# Run generated testskeploy test -c "npm start"
Contract Testing Framework
// Define consumer expectationsawait provider.addInteraction({ state: 'user exists', uponReceiving: 'get user request', withRequest: { method: 'GET', path: '/user/1' }, willRespondWith: { status: 200, body: userData }});
Service Virtualization
stubFor(get(urlEqualTo("/api/user/123")) .willReturn(aResponse() .withStatus(200) .withHeader("Content-Type", "application/json") .withBody(userJson)));
# AI-optimized CI pipeline for integration testsname: Integration Test Suite
on: pull_request: push: branches: [main]
jobs: integration-tests: runs-on: ubuntu-latest
services: postgres: image: postgres:14 env: POSTGRES_PASSWORD: test options: >- --health-cmd pg_isready --health-interval 10s
redis: image: redis:7 options: >- --health-cmd "redis-cli ping" --health-interval 10s
steps: - uses: actions/checkout@v3
- name: Setup Test Environment run: | docker-compose -f docker-compose.test.yml up -d npm run wait-for-services
- name: Run Integration Tests run: | npm run test:integration -- --coverage env: DATABASE_URL: postgres://test:test@localhost:5432/test REDIS_URL: redis://localhost:6379
- name: Run Contract Tests run: | npm run test:contracts npm run pact:publish
- name: Performance Regression Check run: | npm run test:performance -- --compare-with main