Skip to content

Error Testing ​

Error testing is crucial for robust gRPC applications. Learn how to test error conditions, validation failures, and expected error scenarios.

Why Test Errors? ​

Testing error conditions ensures your application:

  • âś… Handles failures gracefully
  • âś… Returns meaningful error messages
  • âś… Maintains security under invalid input
  • âś… Provides helpful debugging information

Basic Error Testing ​

Testing Expected Errors ​

When errors are expected and should occur:

php
--- ENDPOINT ---
user.UserService/GetUser

--- REQUEST ---
{ "user_id": "nonexistent" }

--- ERROR ---
{
  "code": 5,
  "message": "User not found",
  "details": "User with ID 'nonexistent' does not exist"
}

Validating Error Responses ​

Use assertions to validate error details:

php
--- ENDPOINT ---
user.UserService/GetUser

--- REQUEST ---
{ "user_id": "nonexistent" }

--- ASSERTS ---
.code == 5
.message | contains("not found")
.details | contains("does not exist")

Input Validation Testing ​

Testing Invalid Input ​

Test when users provide invalid data:

php
--- ENDPOINT ---
user.UserService/CreateUser

--- REQUEST ---
{
  "name": "",
  "email": "invalid-email",
  "age": -5
}

--- ERROR ---
{
  "code": 3,
  "message": "Invalid input",
  "details": "Name cannot be empty, email format is invalid, age must be positive"
}

Comprehensive Validation Testing ​

php
--- ENDPOINT ---
user.UserService/CreateUser

--- REQUEST ---
{
  "name": "",
  "email": "not-an-email",
  "age": -1
}

--- ASSERTS ---
.code == 3
.message == "Invalid input"
.details | contains("Name cannot be empty")
.details | contains("email format is invalid")
.details | contains("age must be positive")

Authentication Error Testing ​

Testing Missing Authentication ​

php
--- ENDPOINT ---
secure.UserService/GetProfile

--- REQUEST ---
{ "user_id": "123" }

--- ERROR ---
{
  "code": 16,
  "message": "Unauthenticated",
  "details": "Missing or invalid authentication token"
}

Testing Invalid Tokens ​

php
--- ENDPOINT ---
secure.UserService/GetProfile

--- REQUEST_HEADERS ---
authorization: Bearer invalid-token

--- REQUEST ---
{ "user_id": "123" }

--- ERROR ---
{
  "code": 16,
  "message": "Unauthenticated",
  "details": "Invalid authentication token"
}

Authorization Error Testing ​

Testing Insufficient Permissions ​

php
--- ENDPOINT ---
admin.UserService/DeleteUser

--- REQUEST_HEADERS ---
authorization: Bearer user-token

--- REQUEST ---
{ "user_id": "123" }

--- ERROR ---
{
  "code": 7,
  "message": "Permission denied",
  "details": "Insufficient permissions to delete users"
}

Resource Not Found Testing ​

Testing Missing Resources ​

php
--- ENDPOINT ---
product.ProductService/GetProduct

--- REQUEST ---
{ "product_id": "nonexistent" }

--- ERROR ---
{
  "code": 5,
  "message": "Product not found",
  "details": "Product with ID 'nonexistent' does not exist"
}

Testing Deleted Resources ​

php
--- ENDPOINT ---
order.OrderService/GetOrder

--- REQUEST ---
{ "order_id": "deleted_order" }

--- ERROR ---
{
  "code": 5,
  "message": "Order not found",
  "details": "Order has been deleted or does not exist"
}

Rate Limiting Testing ​

Testing Rate Limit Exceeded ​

php
--- ENDPOINT ---
api.SearchService/Search

--- REQUEST ---
{ "query": "test" }

--- ERROR ---
{
  "code": 8,
  "message": "Resource exhausted",
  "details": "Rate limit exceeded. Try again in 60 seconds."
}

Server Error Testing ​

Testing Internal Server Errors ​

php
--- ENDPOINT ---
service.ServiceName/MethodName

--- REQUEST ---
{ "data": "trigger_error" }

--- ERROR ---
{
  "code": 13,
  "message": "Internal server error",
  "details": "An unexpected error occurred"
}

Common Error Codes ​

gRPC Status Codes ​

CodeNameDescriptionUse Case
0OKSuccessNormal operation
1CANCELLEDOperation cancelledClient cancelled request
2UNKNOWNUnknown errorUnexpected server error
3INVALID_ARGUMENTInvalid inputBad request data
4DEADLINE_EXCEEDEDTimeoutRequest took too long
5NOT_FOUNDResource not foundMissing data
6ALREADY_EXISTSResource existsDuplicate creation
7PERMISSION_DENIEDInsufficient permissionsAuthorization failure
8RESOURCE_EXHAUSTEDResource limitsRate limiting, quotas
9FAILED_PRECONDITIONInvalid stateBusiness logic error
10ABORTEDOperation abortedConcurrency conflict
11OUT_OF_RANGEValue out of rangeInvalid parameter value
12UNIMPLEMENTEDNot implementedMissing functionality
13INTERNALInternal errorServer error
14UNAVAILABLEService unavailableService down
15DATA_LOSSData corruptionData integrity issue
16UNAUTHENTICATEDNot authenticatedMissing/invalid auth

Error Testing Patterns ​

Pattern 1: Expected Business Logic Errors ​

php
--- ENDPOINT ---
order.OrderService/CancelOrder

--- REQUEST ---
{ "order_id": "shipped_order" }

--- ERROR ---
{
  "code": 9,
  "message": "Order cannot be cancelled",
  "details": "Order has already been shipped"
}

Pattern 2: Validation Chain Testing ​

php
--- ENDPOINT ---
user.UserService/UpdateProfile

--- REQUEST ---
{
  "user_id": "123",
  "email": "invalid-email",
  "phone": "not-a-phone"
}

--- ASSERTS ---
.code == 3
.message == "Validation failed"
.details | contains("Invalid email format")
.details | contains("Invalid phone format")

Pattern 3: Conditional Error Testing ​

php
--- ENDPOINT ---
payment.PaymentService/ProcessPayment

--- REQUEST ---
{
  "amount": 1000,
  "currency": "USD",
  "card_number": "4111111111111111"
}

--- ASSERTS ---
# Test for either success or specific error
if .code == 0 then
  .transaction_id | length > 0
else
  .code == 3 and .message | contains("Invalid")
end

Best Practices ​

✅ Do This: ​

  1. Test All Error Scenarios

    php
    # Test missing required fields
    # Test invalid data types
    # Test out-of-range values
    # Test authentication failures
    # Test authorization failures
  2. Validate Error Details

    php
    --- ASSERTS ---
    .code == 3
    .message | contains("Invalid")
    .details | contains("specific error")
  3. Test Edge Cases

    php
    # Empty strings
    # Null values
    # Very large numbers
    # Special characters
    # Unicode strings
  4. Use Meaningful Error Messages

    php
    # Good
    "Invalid email format: missing @ symbol"
    
    # Bad
    "Validation failed"

❌ Avoid This: ​

  1. Testing Only Happy Path

    php
    # Don't only test success cases
    # Always test error conditions
  2. Generic Error Messages

    php
    # Bad
    .message == "Error occurred"
    
    # Good
    .message | contains("specific error")
  3. Ignoring Error Codes

    php
    # Bad - not checking error code
    .message | contains("error")
    
    # Good - validate specific code
    .code == 3
    .message | contains("Invalid input")

Common Error Testing Scenarios ​

User Registration Errors ​

php
--- ENDPOINT ---
auth.AuthService/Register

--- REQUEST ---
{
  "email": "invalid-email",
  "password": "123"
}

--- ASSERTS ---
.code == 3
.message | contains("Invalid email")
.details | contains("password too short")

Payment Processing Errors ​

php
--- ENDPOINT ---
payment.PaymentService/Charge

--- REQUEST ---
{
  "amount": -100,
  "card_number": "invalid"
}

--- ASSERTS ---
.code == 3
.message | contains("Invalid amount")
.details | contains("Invalid card")

File Upload Errors ​

php
--- ENDPOINT ---
file.FileService/Upload

--- REQUEST ---
{
  "filename": "",
  "size": 1000000000
}

--- ASSERTS ---
.code == 3
.message | contains("Invalid filename")
.details | contains("File too large")

Next Steps ​

Released under the MIT License.