The Google Cloud Client Libraries for Rust provide helpers that simplify interaction with long-running operations (LROs). Simulating the behavior of LROs in unit tests involves understanding the underlying details that these helpers abstract away. This guide shows you how to write unit tests for both automatic and manual LRO polling, including error scenarios.
Prerequisites
This guide assumes that you are familiar with the following guides:
Test automatic polling
Assume that your application code awaits lro::Poller::until_done() (automatic
polling):
Because the application only uses the final result of the LRO, you don't need to test how it handles intermediate polling results. Your test can return the final result of the LRO directly from the mock.
Create the longrunning::model::Operation
Assume that you want the call to return the following response:
The stub returns a longrunning::model::Operation rather than a
BatchRecognizeResponse. Pack the expected response into Operation::result:
Set the done field to true to indicate to the Poller that the operation is
complete, ending the polling loop:
Write the test
Define the mock struct, which implements the
speech::stub::Speechtrait:In the test, create the mock and set expectations on it:
Create a client from the mock, call the function, and verify the response:
Test manual polling with intermediate metadata
Assume that your application code polls manually and processes partial updates:
You can simulate how the application behaves when it receives intermediate metadata by returning in-progress operations from the mock.
Create the longrunning::model::Operation
The BatchRecognize RPC returns partial results as a
speech::model::OperationMetadata. Pack this metadata into the
Operation::metadata field of the returned longrunning::model::Operation:
Write the test
Define the mock struct, which implements the
speech::stub::Speechtrait and overridesget_operation():In the test, create the mock and set expectations on it to return partial results (25%, 50%, 75%) followed by the final outcome:
Note the following details about how the expectations are configured:
- Initial vs. subsequent RPCs: The first expectation is set on
batch_recognize(), whereas all subsequent expectations are set onget_operation(). The initialBatchRecognizeRPC starts the LRO on the server and returns an operation identifier in thenamefield (omitted from the test code for brevity). From then on, the client library polls the status of that LRO using theGetOperationRPC. - Call ordering: Expectations are registered in a
Sequence. This letsmockallverify the order of the calls and determine whichexpect_get_operationexpectation matches each poll.
- Initial vs. subsequent RPCs: The first expectation is set on
Create a client from the mock, call the function, and verify the response:
Simulate errors
Errors can arise at several points during an LRO.
If your application uses automatic polling, all error sources are equivalent:
until_done() returns the error in the Result, regardless of where it
originated.
Simulating an error starting an LRO
produces the simplest test.
Simulate an error starting an LRO
To simulate an error when starting an LRO, configure the initial request to fail with an error:
For manual polling, the PollingResult::Completed branch receives the error
from starting the LRO, which ends the polling loop:
Simulate an LRO resulting in an error
To simulate an LRO that fails after returning intermediate metadata, return the
error in the final longrunning::model::Operation:
Set expectations to return the failed Operation from get_operation:
In manual polling, the PollingResult::Completed branch receives the error
outcome, ending the polling loop:
Simulate a polling error
Polling loops can also exit when the polling policy is exhausted. When this happens, the client library can't determine definitively whether the LRO completed.
If your application has custom logic to handle polling errors, you can test it
by returning an error directly from the get_operation expectation:
In manual polling, the PollingResult::PollingError branch receives the
simulated polling error:
Complete test code
The following sections show the complete code for the tests described in this guide.