Testing RPC Handlers

Comprehensive Testing Strategies for Custom Handlers

← Back to Building and Integrating Custom RPC Handlers


Introduction

Testing is critical for ensuring your RPC handlers work correctly across all scenarios. A well-tested handler catches edge cases, prevents security vulnerabilities, and provides confidence during deployment.

In this section, you'll learn how to structure unit tests using Google Test, create mock objects and fixtures, implement integration tests, and develop comprehensive test cases that cover happy paths, error conditions, and different user roles.


Google Test Framework Overview

Rippled uses Google Test (gtest) for unit testing. All tests follow a consistent pattern.

Test File Structure

Location: src/tests/rpc/handlers/

//------------------------------------------------------------------------------
/*
    Test file for MyHandler RPC command
*/
//==============================================================================

#include <xrpld/app/main/Application.h>
#include <xrpld/rpc/handlers/Handlers.h>
#include <xrpl/protocol/ErrorCodes.h>
#include <test/jtx.h>
#include <gtest/gtest.h>

namespace ripple {
namespace test {

// Test class
class MyHandlerTest : public ::testing::Test {
protected:
    // Setup called before each test
    void SetUp() override {
        // Initialize test fixtures
    }

    // Teardown called after each test
    void TearDown() override {
        // Clean up test fixtures
    }

    // Test helper methods
    Json::Value callHandler(Json::Value const& params);
};

// Test cases follow below

} // namespace test
} // namespace ripple

Unit Test Structure

Basic Test Case

Test Naming Convention

Follow this pattern for test names:


Test Fixtures and Setup

Creating a Comprehensive Test Fixture

Test Utilities with JTX Framework

Rippled provides the JTX (Joyeux Test eXperience) framework:


Mocking and Dependency Injection

Mock Objects for External Dependencies

Injecting Mocks into Context


Happy Path Tests

Tests for successful operations:


Error Condition Tests

Tests for failure scenarios:


Input Validation Tests

Focused tests for parameter validation:


Role-Based Permission Tests

Test authorization for different roles:


Edge Case Tests

Tests for boundary conditions and unusual scenarios:


Integration Tests

Tests that verify end-to-end functionality:


Test Execution and Coverage

Running Tests

Code Coverage Analysis

Coverage Target

Aim for minimum 80% code coverage:

  • All success paths

  • All error conditions

  • All role-based branches

  • Edge cases


Best Practices for RPC Handler Testing

✅ DO

  • Test all error codes — Every possible error should be tested

  • Test with multiple roles — Verify authorization at each level

  • Use descriptive test names — Make tests self-documenting

  • Test both boundaries — Minimum and maximum values

  • Mock external dependencies — Isolate the code under test

  • Test concurrent access — Ensure thread safety

  • Test with real ledger data — Use JTX to create realistic scenarios

❌ DON'T

  • Skip error path tests — Error handling is as important as success

  • Test implementation details — Test behavior, not internals

  • Use hardcoded test data — Use factories and builders

  • Ignore resource limits — Test DoS prevention

  • Test manually — Automate all tests

  • Skip regression tests — Add test for every bug found


Example: Complete Test Suite


Conclusion

Thorough testing is non-negotiable for production-quality RPC handlers. By combining unit tests with integration tests, using descriptive names, testing all code paths including error conditions, and verifying role-based authorization, you build confidence that your handler will behave correctly under all circumstances. The investment in comprehensive test coverage pays dividends in reduced bugs, easier refactoring, and faster debugging when issues arise.


Last updated