This project demonstrates contract testing using Pact with a complete microservices architecture featuring multiple APIs:
- Frontend: React TypeScript application (Consumer) - β READY
- Backend API 1: User API - ASP.NET Core Web API (Provider) - β READY
- Backend API 2: Product API - ASP.NET Core Web API (Provider) - β READY
- Backend API 3: Order API - ASP.NET Core Web API (Provider) - β READY
- Pact Broker: Contract sharing and verification status - β READY
- Docker: Full containerization of all services - β READY
- Provider States: Implemented in User API and Product API - β READY
Run the complete multiple API demo:
# Start all services
docker-compose up --build -d
# Run the comprehensive demo
scripts/demo-multiple-apis.bat
This showcases how one frontend can have contracts with multiple backend services, demonstrating:
- πͺ Single Consumer (React Frontend) with Multiple Providers (User API + Product API)
- π Independent API Development - Teams can work on different APIs simultaneously
- β‘ Fast Integration Feedback - Catch breaking changes early
- π Living Documentation - Contracts serve as up-to-date API specs
- π‘οΈ Safe API Evolution - Deploy with confidence knowing contracts are verified
Note: Pact verification tests are currently being updated to work with PactNet 5.0.0 API changes. The frontend consumer tests and provider state endpoints are fully implemented.
contract-testing/
βββ frontend/ # React TypeScript app
β βββ src/
β β βββ services/ApiService.ts # API client layer
β β βββ __tests__/pact/ # Pact consumer tests
β β βββ App.tsx # Main application
β β βββ index.tsx # Entry point
β βββ package.json
β βββ Dockerfile
β βββ nginx.conf
βββ backend-api-1/ # User API (with Provider States)
β βββ Program.cs # API implementation
β βββ backend-api-1.csproj
β βββ Dockerfile
βββ backend-api-2/ # Product API
β βββ Program.cs
β βββ backend-api-2.csproj
β βββ Dockerfile
βββ backend-api-3/ # Order API
β βββ Program.cs
β βββ backend-api-3.csproj
β βββ Dockerfile
βββ backend-api-1.tests/ # Pact verification tests (WIP)
βββ scripts/ # Helper scripts
βββ docker-compose.yml # Container orchestration
βββ README.md
- Docker and Docker Compose
- Node.js 18+ (for local frontend development)
- .NET 8 SDK (for local backend development)
# Clone the repository
git clone <repository-url>
cd contract-testing
# Start all services with Docker Compose
docker-compose up --build
Once all containers are running:
- Frontend Application: http://localhost:3000
- User API (Backend 1): http://localhost:4001
- Product API (Backend 2): http://localhost:4002
- Order API (Backend 3): http://localhost:4003
- Pact Broker: http://localhost:9292
Each backend API provides Swagger documentation:
- User API Swagger: http://localhost:4001/swagger
- Product API Swagger: http://localhost:4002/swagger
- Order API Swagger: http://localhost:4003/swagger
The frontend generates contracts by writing Pact consumer tests:
cd frontend
npm install
npm run test:pact
This creates contract files in the pacts/
directory.
After running consumer tests, publish the pacts to the broker:
# From project root
scripts/publish-pacts.bat
# Or manually:
cd frontend
docker run --rm -v %CD%/pacts:/pacts pactfoundation/pact-cli:latest publish /pacts --consumer-app-version=1.0.0 --broker-base-url=http://host.docker.internal:9292
Provider verification tests are being updated to work with PactNet 5.0.0. The backend APIs implement provider states for proper contract testing.
Our implementation includes provider states to ensure consistent test data:
"users exist"
- Sets up sample users for testing"user with id 1 exists"
- Ensures specific user exists"no users exist"
- Clears all users for creation tests
See docs/provider-states-explained.md for detailed explanation.
Visit the Pact Broker at http://localhost:9292 to see:
- All contracts between consumer and providers
- Verification status
- Contract evolution over time
GET /api/users
- Get all usersGET /api/users/{id}
- Get user by IDPOST /api/users
- Create new userGET /health
- Health check- Provider States:
POST /provider-states
- Set up test stateDELETE /provider-states
- Tear down test state
GET /api/products
- Get all productsGET /api/products/{id}
- Get product by IDPOST /api/products
- Create new productGET /health
- Health check
GET /api/orders
- Get all ordersGET /api/orders/{id}
- Get order by IDPOST /api/orders
- Create new orderGET /health
- Health check
All APIs build and run successfully:
# User API
cd backend-api-1
dotnet run # Starts on http://localhost:5000
# Product API
cd backend-api-2
dotnet run # Starts on http://localhost:5000
# Order API
cd backend-api-3
dotnet run # Starts on http://localhost:5000
cd frontend
npm install
npm start # Start development server
npm run test:pact # Run Pact consumer tests
npm run build # Build for production
# Build individual services
docker-compose build backend-api-1
docker-compose build backend-api-2
docker-compose build backend-api-3
docker-compose build frontend
# Start all services
docker-compose up --build
The application uses these environment variables:
Frontend:
REACT_APP_API_1_URL
- User API URL (default: http://localhost:4001)REACT_APP_API_2_URL
- Product API URL (default: http://localhost:4002)REACT_APP_API_3_URL
- Order API URL (default: http://localhost:4003)REACT_APP_PACT_BROKER_URL
- Pact Broker URL (default: http://localhost:9292)
Backends:
PACT_BROKER_BASE_URL
- Pact Broker URL for verificationASPNETCORE_ENVIRONMENT
- ASP.NET Core environment
Component | Technology | Status |
---|---|---|
Frontend | React + TypeScript | β Working |
Backend APIs | ASP.NET Core 8 | β Working |
Contract Testing | Pact (@pact-foundation/pact, PactNet) | π‘ Partial |
Containerization | Docker + Docker Compose | β Working |
API Documentation | Swagger/OpenAPI | β Working |
Broker | Pact Broker | β Working |
Provider States | User API Implementation | β Working |
- All Backend APIs: Build successfully and run in Docker
- Frontend: React app with API integration (builds and runs successfully)
- Provider States: Implemented in User API for consistent testing
- Docker Orchestration: All services containerized and working
- API Documentation: Swagger UI available for all backends
- Pact Consumer Tests: All tests passing for User API and Product API
- Pact Broker: Running and accessible, multiple contracts published successfully
- Contract Publishing: Automated scripts for publishing pacts to broker
- Multiple API Demo: Complete workflow demonstrating frontend contracts with multiple providers
- Pact Verification Tests: Being updated for PactNet 5.0.0 compatibility
# Test API builds
cd backend-api-1 && dotnet build # β
Works
cd backend-api-2 && dotnet build # β
Works
cd backend-api-3 && dotnet build # β
Works
# Test Docker builds
docker-compose build backend-api-1 # β
Works
docker-compose build backend-api-2 # β
Works
docker-compose build backend-api-3 # β
Works
# Start all services
docker-compose up --build # β
Works
# Run contract testing workflow
scripts/run-contract-tests.bat # β
Runs consumer tests + publishes pacts
# Run comprehensive multiple API demo
scripts/demo-multiple-apis.bat # β
Full demo with User + Product APIs
# Just publish pacts (after running consumer tests)
scripts/publish-pacts.bat # β
Publishes to broker
- PactNet Version: Upgrading from 4.6.3 to 5.0.0 requires API changes in verification tests
- Test Project Structure: Moved out of main API directories to prevent build conflicts
To complete this demo:
- Fix PactNet 5.0.0 compatibility in verification tests
- Add provider states to Product API and Order API
- Implement complete consumer tests for all three APIs
- Add automated testing scripts
- Independent Development: Teams can develop and test services independently
- Contract Evolution: Safe API changes with contract compatibility checking
- Fast Feedback: Catch integration issues early without full integration tests
- Documentation: Contracts serve as living documentation
- Confidence: Deploy with confidence knowing contracts are verified
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all APIs build successfully
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.