Skip to content

Commit

Permalink
Add respond_error methods to zebra-test to help with type resolution
Browse files Browse the repository at this point in the history
  • Loading branch information
teor2345 committed May 30, 2023
1 parent ef9cfa0 commit 3717a26
Showing 1 changed file with 106 additions and 2 deletions.
108 changes: 106 additions & 2 deletions zebra-test/src/mock_service.rs
Original file line number Diff line number Diff line change
Expand Up @@ -740,7 +740,9 @@ impl<Request, Response, Error> ResponseSender<Request, Response, Error> {
/// This method takes ownership of the [`ResponseSender`] so that only one response can be
/// sent.
///
/// If `respond` or `respond_with` are not called, the caller will panic.
/// # Panics
///
/// If one of the `respond*` methods isn't called, the caller will panic.
///
/// # Example
///
Expand Down Expand Up @@ -789,7 +791,9 @@ impl<Request, Response, Error> ResponseSender<Request, Response, Error> {
/// This method takes ownership of the [`ResponseSender`] so that only one response can be
/// sent.
///
/// If `respond` or `respond_with` are not called, the caller will panic.
/// # Panics
///
/// If one of the `respond*` methods isn't called, the caller will panic.
///
/// # Example
///
Expand Down Expand Up @@ -834,6 +838,106 @@ impl<Request, Response, Error> ResponseSender<Request, Response, Error> {
let response_result = response_fn(self.request()).into_result();
let _ = self.response_sender.send(response_result);
}

/// Respond to the request using a fixed error value.
///
/// The `error` must be the `Error` type. This helps avoid type resolution issues in the
/// compiler.
///
/// This method takes ownership of the [`ResponseSender`] so that only one response can be
/// sent.
///
/// # Panics
///
/// If one of the `respond*` methods isn't called, the caller will panic.
///
/// # Example
///
/// ```
/// # use zebra_test::mock_service::MockService;
/// # use tower::{Service, ServiceExt};
/// #
/// # let reactor = tokio::runtime::Builder::new_current_thread()
/// # .enable_all()
/// # .build()
/// # .expect("Failed to build Tokio runtime");
/// #
/// # reactor.block_on(async {
/// // Mock a service with a `String` as the service `Error` type.
/// let mut mock_service: MockService<_, _, _, String> =
/// MockService::build().for_unit_tests();
///
/// # let mut service = mock_service.clone();
/// # let task = tokio::spawn(async move {
/// # let first_call_result = (&mut service).oneshot(1).await;
/// # let second_call_result = service.oneshot(1).await;
/// #
/// # (first_call_result, second_call_result)
/// # });
/// #
/// mock_service
/// .expect_request(1)
/// .await
/// .respond_error("Duplicate request");
/// # });
/// ```
pub fn respond_error(self, error: Error) {
// TODO: impl ResponseResult for BoxError/Error trait when overlapping impls are
// better supported by the compiler
let _ = self.response_sender.send(Err(error));
}

/// Respond to the request by calculating an error from the request.
///
/// The `error` must be the `Error` type. This helps avoid type resolution issues in the
/// compiler.
///
/// This method takes ownership of the [`ResponseSender`] so that only one response can be
/// sent.
///
/// # Panics
///
/// If one of the `respond*` methods isn't called, the caller will panic.
///
/// # Example
///
/// ```
/// # use zebra_test::mock_service::MockService;
/// # use tower::{Service, ServiceExt};
/// #
/// # let reactor = tokio::runtime::Builder::new_current_thread()
/// # .enable_all()
/// # .build()
/// # .expect("Failed to build Tokio runtime");
/// #
/// # reactor.block_on(async {
/// // Mock a service with a `String` as the service `Error` type.
/// let mut mock_service: MockService<_, _, _, String> =
/// MockService::build().for_unit_tests();
///
/// # let mut service = mock_service.clone();
/// # let task = tokio::spawn(async move {
/// # let first_call_result = (&mut service).oneshot(1).await;
/// # let second_call_result = service.oneshot(1).await;
/// #
/// # (first_call_result, second_call_result)
/// # });
/// #
/// mock_service
/// .expect_request(1)
/// .await
/// .respond_with_error(|req| format!("Duplicate request: {}", req));
/// # });
/// ```
pub fn respond_with_error<F>(self, response_fn: F)
where
F: FnOnce(&Request) -> Error,
{
// TODO: impl ResponseResult for BoxError/Error trait when overlapping impls are
// better supported by the compiler
let response_result = Err(response_fn(self.request()));
let _ = self.response_sender.send(response_result);
}
}

/// A representation of an assertion type.
Expand Down

0 comments on commit 3717a26

Please sign in to comment.