@@ -12,7 +12,7 @@ use {crate::spinner, solana_clock::MAX_HASH_AGE_IN_SECONDS, std::cmp::min};
12
12
use {
13
13
crate :: {
14
14
http_sender:: HttpSender ,
15
- mock_sender:: { mock_encoded_account, MockSender } ,
15
+ mock_sender:: { mock_encoded_account, MockSender , MocksMap } ,
16
16
rpc_client:: {
17
17
GetConfirmedSignaturesForAddress2Config , RpcClientConfig , SerializableMessage ,
18
18
SerializableTransaction ,
@@ -439,6 +439,101 @@ impl RpcClient {
439
439
RpcClientConfig :: with_commitment ( CommitmentConfig :: default ( ) ) ,
440
440
)
441
441
}
442
+ /// Create a mock `RpcClient`.
443
+ ///
444
+ /// A mock `RpcClient` contains an implementation of [`RpcSender`] that does
445
+ /// not use the network, and instead returns synthetic responses, for use in
446
+ /// tests.
447
+ ///
448
+ /// It is primarily for internal use, with limited customizability, and
449
+ /// behaviors determined by internal Solana test cases. New users should
450
+ /// consider implementing `RpcSender` themselves and constructing
451
+ /// `RpcClient` with [`RpcClient::new_sender`] to get mock behavior.
452
+ ///
453
+ /// Unless directed otherwise, a mock `RpcClient` will generally return a
454
+ /// reasonable default response to any request, at least for [`RpcRequest`]
455
+ /// values for which responses have been implemented.
456
+ ///
457
+ /// This mock can be customized in two ways:
458
+ ///
459
+ /// 1) By changing the `url` argument, which is not actually a URL, but a
460
+ /// simple string directive that changes the mock behavior in specific
461
+ /// scenarios.
462
+ ///
463
+ /// It is customary to set the `url` to "succeeds" for mocks that should
464
+ /// return successfully, though this value is not actually interpreted.
465
+ ///
466
+ /// If `url` is "fails" then any call to `send` will return `Ok(Value::Null)`.
467
+ ///
468
+ /// Other possible values of `url` are specific to different `RpcRequest`
469
+ /// values. Read the implementation of `MockSender` (which is non-public)
470
+ /// for details.
471
+ ///
472
+ /// 2) Custom responses can be configured by providing [`MocksMap`]. This type
473
+ /// is a [`HashMap`] from [`RpcRequest`] to a [`Vec`] of JSON [`Value`] responses,
474
+ /// Any entries in this map override the default behavior for the given
475
+ /// request.
476
+ ///
477
+ /// The [`RpcClient::new_mock_with_mocks_map`] function offers further
478
+ /// customization options.
479
+ ///
480
+ ///
481
+ /// # Examples
482
+ ///
483
+ /// ```
484
+ /// # use solana_rpc_client_api::{
485
+ /// # request::RpcRequest,
486
+ /// # response::{Response, RpcResponseContext},
487
+ /// # };
488
+ /// # use solana_rpc_client::{rpc_client::RpcClient, mock_sender::MocksMap};
489
+ /// # use serde_json::json;
490
+ /// // Create a mock with a custom response to the `GetBalance` request
491
+ /// let account_balance_x = 50;
492
+ /// let account_balance_y = 100;
493
+ /// let account_balance_z = 150;
494
+ /// let account_balance_req_responses = vec![
495
+ /// (
496
+ /// RpcRequest::GetBalance,
497
+ /// json!(Response {
498
+ /// context: RpcResponseContext {
499
+ /// slot: 1,
500
+ /// api_version: None,
501
+ /// },
502
+ /// value: json!(account_balance_x),
503
+ /// })
504
+ /// ),
505
+ /// (
506
+ /// RpcRequest::GetBalance,
507
+ /// json!(Response {
508
+ /// context: RpcResponseContext {
509
+ /// slot: 1,
510
+ /// api_version: None,
511
+ /// },
512
+ /// value: json!(account_balance_y),
513
+ /// })
514
+ /// ),
515
+ /// ];
516
+ ///
517
+ /// let mut mocks = MocksMap::from_iter(account_balance_req_responses);
518
+ /// mocks.insert(
519
+ /// RpcRequest::GetBalance,
520
+ /// json!(Response {
521
+ /// context: RpcResponseContext {
522
+ /// slot: 1,
523
+ /// api_version: None,
524
+ /// },
525
+ /// value: json!(account_balance_z),
526
+ /// }),
527
+ /// );
528
+ /// let url = "succeeds".to_string();
529
+ /// let client = RpcClient::new_mock_with_mocks_map(url, mocks);
530
+ /// ```
531
+ pub fn new_mock_with_mocks_map < U : ToString > ( url : U , mocks : MocksMap ) -> Self {
532
+ Self :: new_sender (
533
+ MockSender :: new_with_mocks_map ( url, mocks) ,
534
+ RpcClientConfig :: with_commitment ( CommitmentConfig :: default ( ) ) ,
535
+ )
536
+ }
442
537
443
538
/// Create an HTTP `RpcClient` from a [`SocketAddr`].
444
539
///
@@ -4707,7 +4802,7 @@ pub(crate) fn parse_keyed_accounts(
4707
4802
4708
4803
#[ doc( hidden) ]
4709
4804
pub fn create_rpc_client_mocks ( ) -> crate :: mock_sender:: Mocks {
4710
- let mut mocks = std :: collections :: HashMap :: new ( ) ;
4805
+ let mut mocks = crate :: mock_sender :: Mocks :: default ( ) ;
4711
4806
4712
4807
let get_account_request = RpcRequest :: GetAccountInfo ;
4713
4808
let get_account_response = serde_json:: to_value ( Response {
0 commit comments