API Integration Testing Skill
Use this skill to perform integration testing of .NET microservices using curl and command-line tools.
When to Use
- •After implementing API endpoints
- •After fixing backend bugs
- •Before deploying backend changes
- •During QA validation
- •For security testing
What This Skill Does
1. JWT Authentication Testing
Validates security implementation:
- •Test endpoints without token (expect 401)
- •Test with invalid token (expect 401)
- •Test with wrong role (expect 403)
- •Test with correct role (expect 200)
2. CRUD Operations Testing
Tests all API operations:
- •CREATE: POST request creates resource
- •READ: GET request returns data
- •UPDATE: PUT request modifies resource
- •DELETE: DELETE request removes resource
3. Business Isolation Testing
Verifies multi-tenancy security:
- •Cannot access other business data
- •Queries filter by business_id from JWT
- •Cross-business access returns 404
4. Validation Testing
Checks input validation:
- •Missing required fields return 400
- •Invalid formats return 400
- •Error messages are user-friendly
5. Health Check Testing
Verifies monitoring:
- •/health endpoint responds 200
- •Database connectivity checked
Testing Tools
Bash Commands Available
- •
curl- HTTP requests to API - •
dotnet build- Compile verification - •
dotnet test- Run unit tests - •
docker-compose- Start services - •
jq- Parse JSON responses (if available)
Expected Inputs
- •API base URL (e.g., http://localhost:8003/api/scheduling)
- •Endpoints to test
- •JWT tokens for different roles
- •Test data payloads
Testing Workflow
Step 1: Build Verification
cd {context}/{context}-api
dotnet build
Expected: 0 errors, 0 warnings
Step 2: Start Service
docker-compose up -d {context}_api
Expected: Container starts successfully
Step 3: Test Health
curl -f http://localhost:{port}/health
Expected: HTTP 200
Step 4: Test Authentication
# No token (should fail)
curl -i http://localhost:{port}/api/{context}/endpoint
# Expected: 401 Unauthorized
# Invalid token (should fail)
curl -i -H "Authorization: Bearer invalid" \
http://localhost:{port}/api/{context}/endpoint
# Expected: 401 Unauthorized
# Valid token (should succeed)
curl -i -H "Authorization: Bearer ${VALID_TOKEN}" \
http://localhost:{port}/api/{context}/endpoint
# Expected: 200 OK
Step 5: Test CRUD
# CREATE
curl -X POST \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name":"Test","value":123}' \
http://localhost:{port}/api/{context}/items
# READ
curl -H "Authorization: Bearer ${TOKEN}" \
http://localhost:{port}/api/{context}/items/{id}
# UPDATE
curl -X PUT \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name":"Updated","value":456}' \
http://localhost:{port}/api/{context}/items/{id}
# DELETE
curl -X DELETE \
-H "Authorization: Bearer ${TOKEN}" \
http://localhost:{port}/api/{context}/items/{id}
Step 6: Test Business Isolation
# Create with Business A token
ITEM_ID=$(curl -X POST \
-H "Authorization: Bearer ${BUSINESS_A_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"name":"A Item"}' \
http://localhost:{port}/api/{context}/items | jq -r '.id')
# Try to access with Business B token (should fail)
curl -i -H "Authorization: Bearer ${BUSINESS_B_TOKEN}" \
http://localhost:{port}/api/{context}/items/${ITEM_ID}
# Expected: 404 Not Found
Step 7: Test Validation
# Missing required field
curl -i -X POST \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"value":123}' \
http://localhost:{port}/api/{context}/items
# Expected: 400 Bad Request with validation error
Step 8: Verify Clean Architecture
# Check response is DTO, not entity # Should NOT have: # - EF Core navigation properties # - Internal business logic methods # - Audit fields (CreatedAt, UpdatedAt) # Should have: # - Only data properties # - Clean, simple structure
Test Scripts Examples
Example 1: Schedule API Test
#!/bin/bash
API_URL="http://localhost:8003/api/scheduling"
TOKEN="eyJhbGc..." # Valid JWT token
echo "Testing Schedule API..."
# Test health
echo "1. Health check..."
curl -f ${API_URL:0:-15}/health || echo "FAIL: Health check"
# Test auth
echo "2. Auth test (no token)..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" ${API_URL}/schedules)
[ "$RESPONSE" = "401" ] && echo "PASS" || echo "FAIL: Expected 401, got $RESPONSE"
# Test CREATE
echo "3. Create schedule..."
CREATED=$(curl -X POST \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"employeeId":"123","date":"2025-01-20","startTime":"09:00","endTime":"17:00"}' \
${API_URL}/schedules)
SCHEDULE_ID=$(echo $CREATED | jq -r '.id')
echo "Created schedule: $SCHEDULE_ID"
# Test READ
echo "4. Read schedule..."
curl -H "Authorization: Bearer ${TOKEN}" \
${API_URL}/schedules/${SCHEDULE_ID} | jq '.'
# Test UPDATE
echo "5. Update schedule..."
curl -X PUT \
-H "Authorization: Bearer ${TOKEN}" \
-H "Content-Type: application/json" \
-d '{"employeeId":"123","date":"2025-01-20","startTime":"09:00","endTime":"18:00"}' \
${API_URL}/schedules/${SCHEDULE_ID} | jq '.'
# Test DELETE
echo "6. Delete schedule..."
curl -X DELETE \
-H "Authorization: Bearer ${TOKEN}" \
${API_URL}/schedules/${SCHEDULE_ID}
# Verify deleted
echo "7. Verify deleted..."
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer ${TOKEN}" \
${API_URL}/schedules/${SCHEDULE_ID})
[ "$RESPONSE" = "404" ] && echo "PASS: Deleted" || echo "FAIL: Still exists"
echo "Tests complete!"
Example 2: Business Isolation Test
#!/bin/bash
API_URL="http://localhost:8003/api/scheduling"
BUSINESS_A_TOKEN="token_for_business_a"
BUSINESS_B_TOKEN="token_for_business_b"
echo "Testing business isolation..."
# Create schedule with Business A
SCHEDULE_ID=$(curl -X POST \
-H "Authorization: Bearer ${BUSINESS_A_TOKEN}" \
-H "Content-Type: application/json" \
-d '{"employeeId":"123","date":"2025-01-20"}' \
${API_URL}/schedules | jq -r '.id')
echo "Created schedule $SCHEDULE_ID for Business A"
# Try to access with Business B (should fail)
RESPONSE=$(curl -s -o /dev/null -w "%{http_code}" \
-H "Authorization: Bearer ${BUSINESS_B_TOKEN}" \
${API_URL}/schedules/${SCHEDULE_ID})
if [ "$RESPONSE" = "404" ]; then
echo "PASS: Business B cannot access Business A data"
else
echo "FAIL: Business B can access Business A data (Security issue!)"
exit 1
fi
Validation Checklist
- • Build succeeds (dotnet build)
- • Tests pass (dotnet test)
- • Health check responds 200
- • JWT required (401 without token)
- • Authorization enforced (403 wrong role)
- • CREATE returns 201
- • READ returns 200
- • UPDATE returns 200
- • DELETE returns 204/200
- • Business isolation works (404 for other business)
- • Validation returns 400
- • Error messages user-friendly
- • Swagger documentation correct
Deliverables
- •Test execution results
- •Pass/fail for each test case
- •HTTP response codes captured
- •Error messages (if any)
- •Security test results
- •Recommendations for fixes
Common Test Failures
401 when token provided
Cause: Token validation misconfigured Check: JWT_SECRET, Issuer, Audience in appsettings.json
403 for correct role
Cause: Policy not matching claim Check: Authorization policy definition, claim names
Can access other business data
Cause: Missing business_id filter Fix: CRITICAL SECURITY ISSUE - Add filtering immediately
500 errors
Cause: Unhandled exceptions Check: Application logs, add try-catch, validation
This skill ensures comprehensive API testing covering functionality, security, and architectural compliance.