Mocking ZaloPay Services for Tests
Relevant source files
The following files were used as context for generating this wiki page:
Introduction
The zalopay gem employs a robust testing strategy to ensure the reliability of its integration with the ZaloPay API without depending on the live service during test runs. This is achieved by mocking all external HTTP requests. The testing framework is built on RSpec and utilizes the VCR and WebMock gems to record and replay ZaloPay API interactions.
This approach isolates the test suite from network failures and API availability issues, resulting in fast, deterministic, and reliable tests. Developers can confidently verify the library's request signing, data formatting, and response parsing logic by testing against pre-recorded, consistent API responses.
Sources: zalopay.gemspec:23-25, spec/spec_helper.rb, spec/zalopay_spec.rb
Core Mocking Components
The testing environment relies on three key development dependencies to intercept and mock HTTP requests.
Sources: zalopay.gemspec:23-25
| Gem | Role |
|---|---|
rspec | The core behavior-driven development (BDD) framework used to structure and run the tests. |
webmock | A library to stub and set expectations on HTTP requests at a low level. It's used by VCR. |
vcr | Records test suite's HTTP interactions and replays them during future test runs for fast, deterministic, accurate tests. |
This diagram illustrates how the components interact during a test run.
Sources: spec/spec_helper.rb:3-9
Test Setup and Configuration
The entire mocking mechanism is configured in spec/spec_helper.rb. This file sets up VCR to work with WebMock and defines how RSpec should handle tests that require API interaction.
Sources: spec/spec_helper.rb
VCR Configuration
VCR is configured to store its recordings, known as "cassettes," in the spec/fixtures/vcr_cassettes directory. It is also configured to hook into WebMock to intercept any outgoing HTTP requests made during the tests.
# spec/spec_helper.rb:6-9
VCR.configure do |c|
c.cassette_library_dir = "spec/fixtures/vcr_cassettes"
c.hook_into :webmock
end
Sources: spec/spec_helper.rb:6-9
RSpec Integration
While VCR can be used manually, the project does not use RSpec's metadata integration for automatic cassette management. Instead, tests explicitly wrap API calls within a VCR.use_cassette block. This provides granular control over which cassette is used for a specific test context.
Sources: spec/zalopay_spec.rb:19, spec/zalopay_spec.rb:34
Mocking ZaloPay API Calls
The tests in spec/zalopay_spec.rb demonstrate the practical application of this mocking strategy. Each test that interacts with a ZaloPay API endpoint is wrapped in a VCR.use_cassette block.
Example: Mocking a CreateOrder Request
In the test for creating an order, the call to client.gateway.create_order(params) is executed within a cassette block named "create_order_success".
- First Run: VCR allows the real HTTP request to proceed to the ZaloPay API. It then records the full request and the corresponding response into a YAML file at
spec/fixtures/vcr_cassettes/create_order_success.yml. - Subsequent Runs: VCR and WebMock intercept the HTTP request. Instead of letting it reach the network, VCR finds the matching request in the cassette and immediately returns the recorded response.
# spec/zalopay_spec.rb:18-24
describe "#create_order" do
it "success" do
VCR.use_cassette("create_order_success") do
params = { "app_user" => "Demo" }
response = client.gateway.create_order(params)
expect(response["return_code"]).to eq(1)
end
end
end
Sources: spec/zalopay_spec.rb:18-24
Sequence of a Mocked API Call
The following diagram shows the sequence of events when a test method like create_order is called within a VCR block.
Key Classes Involved in Testing
The mocking strategy targets the boundary of the system, specifically the ZaloPay::Client class, which is responsible for all external communication.
ZaloPay::Client
This class handles the construction and execution of HTTP POST requests to the ZaloPay API. Its post method is the primary point of interaction that is intercepted by WebMock during tests. It uses HTTParty to perform the request.
Sources: lib/zalopay/client.rb:21-23
ZaloPay::Gateway
The Gateway class provides a high-level interface for payment operations like create_order, get_order_status, and refund. Each of these methods delegates the actual HTTP call to the ZaloPay::Client instance it holds. Tests are written against these Gateway methods to verify the business logic.
Sources: lib/zalaypay/gateway.rb:6-8
Class Relationship
The Gateway class depends on the Client class to perform its operations. This separation allows tests to focus on the Gateway's logic while the Client's network activity is completely mocked.
Sources: lib/zalopay/client.rb, lib/zalopay/gateway.rb