diff --git a/NEXT_CHANGELOG.md b/NEXT_CHANGELOG.md index e1868776e6..9a377f16dc 100644 --- a/NEXT_CHANGELOG.md +++ b/NEXT_CHANGELOG.md @@ -63,7 +63,6 @@ when creating it. It will then be modified to integrate the telemetry plugin's l By [@geal](https://github.com/geal) in https://github.com/apollographql/router/pull/1463 - ### Reorder query planner execution ([PR #1484](https://github.com/apollographql/router/pull/1484)) Query planning is deterministic, it only depends on the query, operation name and query planning @@ -75,6 +74,14 @@ they should happen in a supergraph service. By [@Geal](https://github.com/Geal) in https://github.com/apollographql/router/pull/1464 +### Remove Buffer from Mock*Service ([PR #1440](https://github.com/apollographql/router/pull/1440) + +This removes the usage of `tower_test::mock::Mock` in mocked services because it isolated the service in a task +so panics triggered by mockall were not transmitted up to the unit test that should catch it. +This rewrites the mocked services API to remove the `build()` method, and make them clonable if needed, +using an `expect_clone` call with mockall. + +By [@Geal](https://github.com/Geal) in https://github.com/apollographql/router/pull/1440 ## 🚀 Features ### Expose query plan in extensions for GraphQL response (experimental) ([PR #1470](https://github.com/apollographql/router/pull/1470)) diff --git a/apollo-router/Cargo.toml b/apollo-router/Cargo.toml index a54a308a9f..1bac0bc65f 100644 --- a/apollo-router/Cargo.toml +++ b/apollo-router/Cargo.toml @@ -136,7 +136,6 @@ tower-http = { version = "0.3.4", features = [ "timeout" ] } tower-service = "0.3.2" -tower-test = "0.4.0" tracing = "=0.1.34" tracing-core = "=0.1.26" tracing-futures = { version = "0.2.5", features = ["futures-03"] } diff --git a/apollo-router/src/layers/async_checkpoint.rs b/apollo-router/src/layers/async_checkpoint.rs index 38c1134dcb..0a96c8bbb9 100644 --- a/apollo-router/src/layers/async_checkpoint.rs +++ b/apollo-router/src/layers/async_checkpoint.rs @@ -153,23 +153,24 @@ mod async_checkpoint_tests { let expected_label = "from_mock_service"; let mut execution_service = MockExecutionService::new(); - - execution_service - .expect_call() - .times(1) - .returning(move |_req: crate::ExecutionRequest| { - Ok(ExecutionResponse::fake_builder() - .label(expected_label.to_string()) - .build()) - }); - - let service = execution_service.build(); + execution_service.expect_clone().return_once(move || { + let mut execution_service = MockExecutionService::new(); + execution_service.expect_call().times(1).returning( + move |_req: crate::ExecutionRequest| { + Ok(ExecutionResponse::fake_builder() + .label(expected_label.to_string()) + .build()) + }, + ); + + execution_service + }); let service_stack = ServiceBuilder::new() .checkpoint_async(|req: crate::ExecutionRequest| async { Ok(ControlFlow::Continue(req)) }) - .service(service); + .service(execution_service); let request = ExecutionRequest::fake_builder().build(); @@ -191,20 +192,22 @@ mod async_checkpoint_tests { let expected_label = "from_mock_service"; let mut router_service = MockExecutionService::new(); - router_service - .expect_call() - .times(1) - .returning(move |_req| { - Ok(ExecutionResponse::fake_builder() - .label(expected_label.to_string()) - .build()) - }); - - let service = router_service.build(); + router_service.expect_clone().return_once(move || { + let mut router_service = MockExecutionService::new(); + router_service + .expect_call() + .times(1) + .returning(move |_req| { + Ok(ExecutionResponse::fake_builder() + .label(expected_label.to_string()) + .build()) + }); + router_service + }); let service_stack = AsyncCheckpointLayer::new(|req| async { Ok(ControlFlow::Continue(req)) }) - .layer(service); + .layer(router_service); let request = ExecutionRequest::fake_builder().build(); @@ -224,9 +227,10 @@ mod async_checkpoint_tests { #[tokio::test] async fn test_return() { let expected_label = "returned_before_mock_service"; - let router_service = MockExecutionService::new(); - - let service = router_service.build(); + let mut router_service = MockExecutionService::new(); + router_service + .expect_clone() + .return_once(MockExecutionService::new); let service_stack = AsyncCheckpointLayer::new(|_req| async { Ok(ControlFlow::Break( @@ -235,7 +239,7 @@ mod async_checkpoint_tests { .build(), )) }) - .layer(service); + .layer(router_service); let request = ExecutionRequest::fake_builder().build(); @@ -255,15 +259,16 @@ mod async_checkpoint_tests { #[tokio::test] async fn test_error() { let expected_error = "checkpoint_error"; - let router_service = MockExecutionService::new(); - - let service = router_service.build(); + let mut router_service = MockExecutionService::new(); + router_service + .expect_clone() + .return_once(MockExecutionService::new); let service_stack = AsyncCheckpointLayer::new( move |_req| async move { Err(BoxError::from(expected_error)) }, ) - .layer(service); + .layer(router_service); let request = ExecutionRequest::fake_builder().build(); diff --git a/apollo-router/src/layers/cache.rs b/apollo-router/src/layers/cache.rs index 58c65d5b74..0071a1af7c 100644 --- a/apollo-router/src/layers/cache.rs +++ b/apollo-router/src/layers/cache.rs @@ -170,6 +170,7 @@ where } #[cfg(test)] +#[allow(dead_code, unreachable_pub)] mod test { use std::time::Duration; @@ -225,6 +226,8 @@ mod test { }) }); + mock_service.expect_clone().return_once(MockABService::new); + let mut service = create_service(mock_service); let expected = Ok(B { @@ -255,13 +258,14 @@ mod test { } #[tokio::test] - async fn is_should_cache_err() { + async fn it_should_cache_err() { let mut mock_service = MockABService::new(); mock_service .expect_call() .times(1) .returning(move |a| Err(BoxError::from(format!("{} err", a.key)))); + mock_service.expect_clone().return_once(MockABService::new); let mut service = create_service(mock_service); @@ -295,7 +299,7 @@ mod test { mock_service .expect_call() - .times(2) + .times(1) .with(eq(A { key: "Not cacheable".into(), value: "Needed".into(), @@ -306,6 +310,25 @@ mod test { value: "there".into(), }) }); + mock_service.expect_clone().return_once(move || { + let mut mock_service = MockABService::new(); + mock_service + .expect_call() + .times(1) + .with(eq(A { + key: "Not cacheable".into(), + value: "Needed".into(), + })) + .returning(move |a| { + Ok(B { + key: a.key, + value: "there".into(), + }) + }); + mock_service.expect_clone().return_once(MockABService::new); + + mock_service + }); let mut service = create_service(mock_service); @@ -324,7 +347,7 @@ mod test { } #[tokio::test] - async fn it_should_dedupe_in_flight_calls() { + async fn it_should_deduplicate_in_flight_calls() { let mut mock_service = MockABService::new(); mock_service @@ -340,6 +363,7 @@ mod test { value: "there".into(), }) }); + mock_service.expect_clone().return_once(MockABService::new); let mut service = create_service(mock_service); @@ -387,7 +411,7 @@ mod test { }, )) .filter_async(Slow::default()) - .service(mock_service.build()) + .service(mock_service) .map_err(|e: BoxError| e.to_string()) } } diff --git a/apollo-router/src/layers/map_future_with_context.rs b/apollo-router/src/layers/map_future_with_context.rs index bdbca1bd4b..c7c39f3fb2 100644 --- a/apollo-router/src/layers/map_future_with_context.rs +++ b/apollo-router/src/layers/map_future_with_context.rs @@ -114,7 +114,7 @@ mod test { }) }, ) - .service(mock_service.build()); + .service(mock_service); let result = service .ready() diff --git a/apollo-router/src/layers/sync_checkpoint.rs b/apollo-router/src/layers/sync_checkpoint.rs index d3a97ee130..3f84ad0563 100644 --- a/apollo-router/src/layers/sync_checkpoint.rs +++ b/apollo-router/src/layers/sync_checkpoint.rs @@ -191,11 +191,9 @@ mod checkpoint_tests { .build()) }); - let service = execution_service.build(); - let service_stack = ServiceBuilder::new() .checkpoint(|req: crate::ExecutionRequest| Ok(ControlFlow::Continue(req))) - .service(service); + .service(execution_service); let request = ExecutionRequest::fake_builder().build(); @@ -226,10 +224,8 @@ mod checkpoint_tests { .build()) }); - let service = router_service.build(); - let service_stack = - CheckpointLayer::new(|req| Ok(ControlFlow::Continue(req))).layer(service); + CheckpointLayer::new(|req| Ok(ControlFlow::Continue(req))).layer(router_service); let request = ExecutionRequest::fake_builder().build(); @@ -251,8 +247,6 @@ mod checkpoint_tests { let expected_label = "returned_before_mock_service"; let router_service = MockExecutionService::new(); - let service = router_service.build(); - let service_stack = CheckpointLayer::new(|_req| { Ok(ControlFlow::Break( ExecutionResponse::fake_builder() @@ -260,7 +254,7 @@ mod checkpoint_tests { .build(), )) }) - .layer(service); + .layer(router_service); let request = ExecutionRequest::fake_builder().build(); @@ -282,10 +276,8 @@ mod checkpoint_tests { let expected_error = "checkpoint_error"; let router_service = MockExecutionService::new(); - let service = router_service.build(); - - let service_stack = - CheckpointLayer::new(move |_req| Err(BoxError::from(expected_error))).layer(service); + let service_stack = CheckpointLayer::new(move |_req| Err(BoxError::from(expected_error))) + .layer(router_service); let request = ExecutionRequest::fake_builder().build(); diff --git a/apollo-router/src/plugin/test/mod.rs b/apollo-router/src/plugin/test/mod.rs index c2af57027c..511aeb5369 100644 --- a/apollo-router/src/plugin/test/mod.rs +++ b/apollo-router/src/plugin/test/mod.rs @@ -28,6 +28,7 @@ use crate::query_planner::BridgeQueryPlanner; use crate::query_planner::CachingQueryPlanner; use crate::services::layers::apq::APQLayer; use crate::services::layers::ensure_query_presence::EnsureQueryPresence; +use crate::services::subgraph_service::MakeSubgraphService; use crate::services::subgraph_service::SubgraphServiceFactory; use crate::services::ExecutionCreator; use crate::services::Plugins; @@ -94,38 +95,19 @@ impl PluginTestHarness { schema: IntoSchema, mock_router_service: Option, mock_query_planner_service: Option, - mock_subgraph_services: HashMap, + mut subgraph_services: HashMap>, ) -> Result { - let mut subgraph_services = mock_subgraph_services - .into_iter() - .map(|(k, v)| (k, Buffer::new(v.build().boxed(), DEFAULT_BUFFER_SIZE))) - .collect::>(); // If we're using the canned schema then add some canned results if let IntoSchema::Canned = schema { subgraph_services .entry("products".to_string()) - .or_insert_with(|| { - Buffer::new( - mock::canned::products_subgraph().boxed(), - DEFAULT_BUFFER_SIZE, - ) - }); + .or_insert_with(|| Arc::new(mock::canned::products_subgraph())); subgraph_services .entry("accounts".to_string()) - .or_insert_with(|| { - Buffer::new( - mock::canned::accounts_subgraph().boxed(), - DEFAULT_BUFFER_SIZE, - ) - }); + .or_insert_with(|| Arc::new(mock::canned::accounts_subgraph())); subgraph_services .entry("reviews".to_string()) - .or_insert_with(|| { - Buffer::new( - mock::canned::reviews_subgraph().boxed(), - DEFAULT_BUFFER_SIZE, - ) - }); + .or_insert_with(|| Arc::new(mock::canned::reviews_subgraph())); } let schema = Arc::new(schema.into_schema(&Default::default())); @@ -143,7 +125,7 @@ impl PluginTestHarness { .boxed(); let query_planner_service = plugin.query_planning_service( mock_query_planner_service - .map(|s| s.build().boxed()) + .map(|s| s.boxed()) .unwrap_or(query_planner), ); @@ -155,27 +137,22 @@ impl PluginTestHarness { let plugins = Arc::new(plugins); let apq = APQLayer::with_cache(DeduplicatingCache::new().await); - let router_service = mock_router_service - .map(|s| s.build().boxed()) - .unwrap_or_else(|| { - BoxService::new( - RouterService::builder() - .query_planner_service(Buffer::new( - query_planner_service, - DEFAULT_BUFFER_SIZE, - )) - .execution_service_factory(ExecutionCreator { - schema: schema.clone(), + let router_service = mock_router_service.map(|s| s.boxed()).unwrap_or_else(|| { + BoxService::new( + RouterService::builder() + .query_planner_service(Buffer::new(query_planner_service, DEFAULT_BUFFER_SIZE)) + .execution_service_factory(ExecutionCreator { + schema: schema.clone(), + plugins: plugins.clone(), + subgraph_creator: Arc::new(MockSubgraphFactory { plugins: plugins.clone(), - subgraph_creator: Arc::new(MockSubgraphFactory { - plugins: plugins.clone(), - subgraphs: subgraph_services, - }), - }) - .schema(schema.clone()) - .build(), - ) - }); + subgraphs: subgraph_services, + }), + }) + .schema(schema.clone()) + .build(), + ) + }); let router_service = ServiceBuilder::new() .layer(apq) .layer(EnsureQueryPresence::default()) @@ -211,13 +188,7 @@ impl PluginTestHarness { #[derive(Clone)] pub struct MockSubgraphFactory { - pub(crate) subgraphs: HashMap< - String, - Buffer< - BoxService, - SubgraphRequest, - >, - >, + pub(crate) subgraphs: HashMap>, pub(crate) plugins: Arc, } @@ -234,9 +205,7 @@ impl SubgraphServiceFactory for MockSubgraphFactory { self.plugins .iter() .rev() - .fold(service.clone().boxed(), |acc, (_, e)| { - e.subgraph_service(name, acc) - }) + .fold(service.make(), |acc, (_, e)| e.subgraph_service(name, acc)) }) } } diff --git a/apollo-router/src/plugin/test/service.rs b/apollo-router/src/plugin/test/service.rs index 0ac6491e84..ac840e2819 100644 --- a/apollo-router/src/plugin/test/service.rs +++ b/apollo-router/src/plugin/test/service.rs @@ -1,3 +1,4 @@ +#![allow(dead_code, unreachable_pub)] use crate::ExecutionRequest; use crate::ExecutionResponse; use crate::QueryPlannerRequest; @@ -12,29 +13,31 @@ use crate::SubgraphResponse; macro_rules! mock_service { ($name:ident, $request_type:ty, $response_type:ty) => { paste::item! { - #[mockall::automock] - #[allow(dead_code, unreachable_pub)] - pub trait [<$name Service>] { - fn call(&self, req: $request_type) -> Result<$response_type, tower::BoxError>; - } + mockall::mock! { + #[derive(Debug)] + #[allow(dead_code)] + pub [<$name Service>] { + pub fn call(&mut self, req: $request_type) -> Result<$response_type, tower::BoxError>; + } - impl [] { - #[allow(unreachable_pub)] - pub fn build(self) -> tower_test::mock::Mock<$request_type,$response_type> { - let (service, mut handle) = tower_test::mock::spawn(); + #[allow(dead_code)] + impl Clone for [<$name Service>] { + fn clone(&self) -> []; + } + } - tokio::spawn(async move { - loop { - while let Some((request, responder)) = handle.next_request().await { - match self.call(request) { - Ok(response) => responder.send_response(response), - Err(err) => responder.send_error(err), - } - } - } - }); + // mockall does not handle well the lifetime on Context + impl tower::Service<$request_type> for [] { + type Response = $response_type; + type Error = tower::BoxError; + type Future = futures::future::BoxFuture<'static, Result>; - service.into_inner() + fn poll_ready(&mut self, _cx: &mut std::task::Context<'_>) -> std::task::Poll> { + std::task::Poll::Ready(Ok(())) + } + fn call(&mut self, req: $request_type) -> Self::Future { + let r = self.call(req); + Box::pin(async move { r }) } } } diff --git a/apollo-router/src/plugins/csrf.rs b/apollo-router/src/plugins/csrf.rs index 0b2130424e..a8a80746cd 100644 --- a/apollo-router/src/plugins/csrf.rs +++ b/apollo-router/src/plugins/csrf.rs @@ -310,11 +310,10 @@ mod csrf_tests { .unwrap()) }); - let mock = mock_service.build(); let service_stack = Csrf::new(PluginInit::new(config, Default::default())) .await .unwrap() - .router_service(mock.boxed()); + .router_service(mock_service.boxed()); let res = service_stack .oneshot(request) .await @@ -327,11 +326,10 @@ mod csrf_tests { } async fn assert_rejected(config: CSRFConfig, request: RouterRequest) { - let mock = MockRouterService::new().build(); let service_stack = Csrf::new(PluginInit::new(config, Default::default())) .await .unwrap() - .router_service(mock.boxed()); + .router_service(MockRouterService::new().boxed()); let res = service_stack .oneshot(request) .await diff --git a/apollo-router/src/plugins/forbid_mutations.rs b/apollo-router/src/plugins/forbid_mutations.rs index b5037bda24..b335cf997d 100644 --- a/apollo-router/src/plugins/forbid_mutations.rs +++ b/apollo-router/src/plugins/forbid_mutations.rs @@ -89,12 +89,10 @@ mod forbid_http_get_mutations_tests { .times(1) .returning(move |_| Ok(ExecutionResponse::fake_builder().build())); - let mock = mock_service.build(); - let service_stack = ForbidMutations::new(PluginInit::new(true, Default::default())) .await .expect("couldnt' create forbid mutations plugin") - .execution_service(mock.boxed()); + .execution_service(mock_service.boxed()); let request = create_request(Method::GET, OperationKind::Query); @@ -117,11 +115,10 @@ mod forbid_http_get_mutations_tests { }; let expected_status = StatusCode::BAD_REQUEST; - let mock = MockExecutionService::new().build(); let service_stack = ForbidMutations::new(PluginInit::new(true, Default::default())) .await .expect("couldnt' create forbid mutations plugin") - .execution_service(mock.boxed()); + .execution_service(MockExecutionService::new().boxed()); let request = create_request(Method::GET, OperationKind::Mutation); let mut actual_error = service_stack.oneshot(request).await.unwrap(); @@ -139,12 +136,10 @@ mod forbid_http_get_mutations_tests { .times(1) .returning(move |_| Ok(ExecutionResponse::fake_builder().build())); - let mock = mock_service.build(); - let service_stack = ForbidMutations::new(PluginInit::new(false, Default::default())) .await .expect("couldnt' create forbid mutations plugin") - .execution_service(mock.boxed()); + .execution_service(mock_service.boxed()); let request = create_request(Method::GET, OperationKind::Mutation); diff --git a/apollo-router/src/plugins/headers.rs b/apollo-router/src/plugins/headers.rs index 99c9df4822..cf77b72cbb 100644 --- a/apollo-router/src/plugins/headers.rs +++ b/apollo-router/src/plugins/headers.rs @@ -387,7 +387,7 @@ mod test { name: "c".try_into()?, value: "d".try_into()?, })]) - .layer(mock.build()); + .layer(mock); service.ready().await?.call(example_request()).await?; Ok(()) @@ -402,8 +402,7 @@ mod test { .returning(example_response); let mut service = - HeadersLayer::new(vec![Operation::Remove(Remove::Named("aa".try_into()?))]) - .layer(mock.build()); + HeadersLayer::new(vec![Operation::Remove(Remove::Named("aa".try_into()?))]).layer(mock); service.ready().await?.call(example_request()).await?; Ok(()) @@ -420,7 +419,7 @@ mod test { let mut service = HeadersLayer::new(vec![Operation::Remove(Remove::Matching( Regex::from_str("a[ab]")?, ))]) - .layer(mock.build()); + .layer(mock); service.ready().await?.call(example_request()).await?; Ok(()) @@ -445,7 +444,7 @@ mod test { let mut service = HeadersLayer::new(vec![Operation::Propagate(Propagate::Matching { matching: Regex::from_str("d[ab]")?, })]) - .layer(mock.build()); + .layer(mock); service.ready().await?.call(example_request()).await?; Ok(()) @@ -471,7 +470,7 @@ mod test { rename: None, default: None, })]) - .layer(mock.build()); + .layer(mock); service.ready().await?.call(example_request()).await?; Ok(()) @@ -497,7 +496,7 @@ mod test { rename: Some("ea".try_into()?), default: None, })]) - .layer(mock.build()); + .layer(mock); service.ready().await?.call(example_request()).await?; Ok(()) @@ -523,7 +522,7 @@ mod test { rename: None, default: Some("defaulted".try_into()?), })]) - .layer(mock.build()); + .layer(mock); service.ready().await?.call(example_request()).await?; Ok(()) diff --git a/apollo-router/src/plugins/override_url.rs b/apollo-router/src/plugins/override_url.rs index 22b98ae7d2..0147a10f25 100644 --- a/apollo-router/src/plugins/override_url.rs +++ b/apollo-router/src/plugins/override_url.rs @@ -100,7 +100,7 @@ mod tests { .await .unwrap(); let mut subgraph_service = - dyn_plugin.subgraph_service("test_one", BoxService::new(mock_service.build())); + dyn_plugin.subgraph_service("test_one", BoxService::new(mock_service)); let context = Context::new(); context.insert("test".to_string(), 5i64).unwrap(); let subgraph_req = SubgraphRequest::fake_builder().context(context); diff --git a/apollo-router/src/plugins/rhai.rs b/apollo-router/src/plugins/rhai.rs index 48ab13e275..fc34b79610 100644 --- a/apollo-router/src/plugins/rhai.rs +++ b/apollo-router/src/plugins/rhai.rs @@ -1436,7 +1436,7 @@ mod tests { ) .await .unwrap(); - let mut router_service = dyn_plugin.router_service(BoxService::new(mock_service.build())); + let mut router_service = dyn_plugin.router_service(BoxService::new(mock_service)); let context = Context::new(); context.insert("test", 5i64).unwrap(); let router_req = RouterRequest::fake_builder().context(context).build()?; @@ -1471,14 +1471,19 @@ mod tests { #[tokio::test] async fn rhai_plugin_execution_service_error() -> Result<(), BoxError> { let mut mock_service = MockExecutionService::new(); - mock_service - .expect_call() - .times(1) - .returning(move |req: ExecutionRequest| { - Ok(ExecutionResponse::fake_builder() - .context(req.context) - .build()) - }); + mock_service.expect_clone().return_once(move || { + let mut mock_service = MockExecutionService::new(); + mock_service + .expect_call() + .times(1) + .returning(move |req: ExecutionRequest| { + Ok(ExecutionResponse::fake_builder() + .context(req.context) + .build()) + }); + + mock_service + }); let dyn_plugin: Box = crate::plugin::plugins() .get("apollo.rhai") @@ -1489,8 +1494,7 @@ mod tests { ) .await .unwrap(); - let mut router_service = - dyn_plugin.execution_service(BoxService::new(mock_service.build())); + let mut router_service = dyn_plugin.execution_service(BoxService::new(mock_service)); let fake_req = http_ext::Request::fake_builder() .header("x-custom-header", "CUSTOM_VALUE") .body(Request::builder().query(String::new()).build()) diff --git a/apollo-router/src/plugins/telemetry/mod.rs b/apollo-router/src/plugins/telemetry/mod.rs index a238035e5c..99e705cc63 100644 --- a/apollo-router/src/plugins/telemetry/mod.rs +++ b/apollo-router/src/plugins/telemetry/mod.rs @@ -1337,7 +1337,7 @@ mod tests { ) .await .unwrap(); - let mut router_service = dyn_plugin.router_service(BoxService::new(mock_service.build())); + let mut router_service = dyn_plugin.router_service(BoxService::new(mock_service)); let router_req = RouterRequest::fake_builder().header("test", "my_value_set"); let _router_response = router_service @@ -1351,10 +1351,8 @@ mod tests { .await .unwrap(); - let mut subgraph_service = dyn_plugin.subgraph_service( - "my_subgraph_name", - BoxService::new(mock_subgraph_service.build()), - ); + let mut subgraph_service = + dyn_plugin.subgraph_service("my_subgraph_name", BoxService::new(mock_subgraph_service)); let subgraph_req = SubgraphRequest::fake_builder() .subgraph_request( http_ext::Request::fake_builder() @@ -1378,7 +1376,7 @@ mod tests { // Another subgraph let mut subgraph_service = dyn_plugin.subgraph_service( "my_subgraph_name_error", - BoxService::new(mock_subgraph_service_in_error.build()), + BoxService::new(mock_subgraph_service_in_error), ); let subgraph_req = SubgraphRequest::fake_builder() .subgraph_request( diff --git a/apollo-router/src/plugins/traffic_shaping/mod.rs b/apollo-router/src/plugins/traffic_shaping/mod.rs index 973d18ef8f..4130061035 100644 --- a/apollo-router/src/plugins/traffic_shaping/mod.rs +++ b/apollo-router/src/plugins/traffic_shaping/mod.rs @@ -526,13 +526,17 @@ mod test { let plugin = get_traffic_shaping_plugin(&config).await; let mut mock_service = MockRouterService::new(); - mock_service.expect_call().times(2).returning(move |_| { - Ok(RouterResponse::fake_builder() - .data(json!({ "test": 1234_u32 })) - .build() - .unwrap()) + mock_service.expect_clone().returning(|| { + let mut mock_service = MockRouterService::new(); + + mock_service.expect_call().times(0..2).returning(move |_| { + Ok(RouterResponse::fake_builder() + .data(json!({ "test": 1234_u32 })) + .build() + .unwrap()) + }); + mock_service }); - let mock_service = mock_service.build(); let _response = plugin .router_service(mock_service.clone().boxed()) diff --git a/apollo-router/src/query_planner/mod.rs b/apollo-router/src/query_planner/mod.rs index 0808f8b23d..0e4f4b0a0e 100644 --- a/apollo-router/src/query_planner/mod.rs +++ b/apollo-router/src/query_planner/mod.rs @@ -1191,13 +1191,12 @@ mod tests { use std::sync::Arc; use http::Method; - use tower::ServiceBuilder; - use tower::ServiceExt; use super::*; use crate::json_ext::PathElement; use crate::plugin::test::MockSubgraphFactory; use crate::query_planner::fetch::FetchNode; + use crate::services::subgraph_service::MakeSubgraphService; macro_rules! test_query_plan { () => { @@ -1237,6 +1236,7 @@ mod tests { /// The query planner reports the failed subgraph fetch as an error with a reason of "service /// closed", which is what this test expects. #[tokio::test] + #[should_panic(expected = "this panic should be propagated to the test harness")] async fn mock_subgraph_service_withf_panics_should_be_reported_as_service_closed() { let query_plan: QueryPlan = QueryPlan { root: serde_json::from_str(test_query_plan!()).unwrap(), @@ -1251,14 +1251,19 @@ mod tests { mock_products_service.expect_call().times(1).withf(|_| { panic!("this panic should be propagated to the test harness"); }); + mock_products_service.expect_clone().return_once(|| { + let mut mock_products_service = plugin::test::MockSubgraphService::new(); + mock_products_service.expect_call().times(1).withf(|_| { + panic!("this panic should be propagated to the test harness"); + }); + mock_products_service + }); let (sender, _) = futures::channel::mpsc::channel(10); let sf = Arc::new(MockSubgraphFactory { subgraphs: HashMap::from([( "product".into(), - ServiceBuilder::new() - .buffer(1) - .service(mock_products_service.build().boxed()), + Arc::new(mock_products_service) as Arc, )]), plugins: Default::default(), }); @@ -1301,25 +1306,27 @@ mod tests { let inner_succeeded = Arc::clone(&succeeded); let mut mock_products_service = plugin::test::MockSubgraphService::new(); - mock_products_service - .expect_call() - .times(1) - .withf(move |request| { - let matches = request.subgraph_request.body().operation_name - == Some("topProducts_product_0".into()); - inner_succeeded.store(matches, Ordering::SeqCst); - matches - }) - .returning(|_| Ok(SubgraphResponse::fake_builder().build())); + mock_products_service.expect_clone().return_once(|| { + let mut mock_products_service = plugin::test::MockSubgraphService::new(); + mock_products_service + .expect_call() + .times(1) + .withf(move |request| { + let matches = request.subgraph_request.body().operation_name + == Some("topProducts_product_0".into()); + inner_succeeded.store(matches, Ordering::SeqCst); + matches + }) + .returning(|_| Ok(SubgraphResponse::fake_builder().build())); + mock_products_service + }); let (sender, _) = futures::channel::mpsc::channel(10); let sf = Arc::new(MockSubgraphFactory { subgraphs: HashMap::from([( "product".into(), - ServiceBuilder::new() - .buffer(1) - .service(mock_products_service.build().boxed()), + Arc::new(mock_products_service) as Arc, )]), plugins: Default::default(), }); @@ -1358,23 +1365,27 @@ mod tests { let inner_succeeded = Arc::clone(&succeeded); let mut mock_products_service = plugin::test::MockSubgraphService::new(); - mock_products_service - .expect_call() - .times(1) - .withf(move |request| { - let matches = request.subgraph_request.method() == Method::POST; - inner_succeeded.store(matches, Ordering::SeqCst); - matches - }) - .returning(|_| Ok(SubgraphResponse::fake_builder().build())); + + mock_products_service.expect_clone().return_once(|| { + let mut mock_products_service = plugin::test::MockSubgraphService::new(); + mock_products_service + .expect_call() + .times(1) + .withf(move |request| { + let matches = request.subgraph_request.method() == Method::POST; + inner_succeeded.store(matches, Ordering::SeqCst); + matches + }) + .returning(|_| Ok(SubgraphResponse::fake_builder().build())); + mock_products_service + }); + let (sender, _) = futures::channel::mpsc::channel(10); let sf = Arc::new(MockSubgraphFactory { subgraphs: HashMap::from([( "product".into(), - ServiceBuilder::new() - .buffer(1) - .service(mock_products_service.build().boxed()), + Arc::new(mock_products_service) as Arc, )]), plugins: Default::default(), }); @@ -1469,32 +1480,41 @@ mod tests { }; let mut mock_x_service = plugin::test::MockSubgraphService::new(); - mock_x_service - .expect_call() - .times(1) - .withf(move |_request| true) - .returning(|_| { - Ok(SubgraphResponse::fake_builder() - .data(serde_json::json! {{ - "t": {"id": 1234, - "__typename": "T", - "x": "X" - } - }}) - .build()) - }); + mock_x_service.expect_clone().return_once(|| { + let mut mock_x_service = plugin::test::MockSubgraphService::new(); + mock_x_service + .expect_call() + .times(1) + .withf(move |_request| true) + .returning(|_| { + Ok(SubgraphResponse::fake_builder() + .data(serde_json::json! {{ + "t": {"id": 1234, + "__typename": "T", + "x": "X" + } + }}) + .build()) + }); + mock_x_service + }); + let mut mock_y_service = plugin::test::MockSubgraphService::new(); - mock_y_service - .expect_call() - .times(1) - .withf(move |_request| true) - .returning(|_| { - Ok(SubgraphResponse::fake_builder() - .data(serde_json::json! {{ - "_entities": [{"y": "Y", "__typename": "T"}] - }}) - .build()) - }); + mock_y_service.expect_clone().return_once(|| { + let mut mock_y_service = plugin::test::MockSubgraphService::new(); + mock_y_service + .expect_call() + .times(1) + .withf(move |_request| true) + .returning(|_| { + Ok(SubgraphResponse::fake_builder() + .data(serde_json::json! {{ + "_entities": [{"y": "Y", "__typename": "T"}] + }}) + .build()) + }); + mock_y_service + }); let (sender, mut receiver) = futures::channel::mpsc::channel(10); @@ -1504,15 +1524,11 @@ mod tests { subgraphs: HashMap::from([ ( "X".into(), - ServiceBuilder::new() - .buffer(1) - .service(mock_x_service.build().boxed()), + Arc::new(mock_x_service) as Arc, ), ( "Y".into(), - ServiceBuilder::new() - .buffer(1) - .service(mock_y_service.build().boxed()), + Arc::new(mock_y_service) as Arc, ), ]), plugins: Default::default(), @@ -1625,10 +1641,15 @@ mod tests { }; let mut mock_a_service = plugin::test::MockSubgraphService::new(); - mock_a_service - .expect_call() - .times(1) - .returning(|_| Ok(SubgraphResponse::fake_builder().build())); + mock_a_service.expect_clone().returning(|| { + let mut mock_a_service = plugin::test::MockSubgraphService::new(); + mock_a_service + .expect_call() + .times(1) + .returning(|_| Ok(SubgraphResponse::fake_builder().build())); + + mock_a_service + }); // the first fetch returned null, so there should never be a call to B let mut mock_b_service = plugin::test::MockSubgraphService::new(); @@ -1638,15 +1659,11 @@ mod tests { subgraphs: HashMap::from([ ( "A".into(), - ServiceBuilder::new() - .buffer(1) - .service(mock_a_service.build().boxed()), + Arc::new(mock_a_service) as Arc, ), ( "B".into(), - ServiceBuilder::new() - .buffer(1) - .service(mock_b_service.build().boxed()), + Arc::new(mock_b_service) as Arc, ), ]), plugins: Default::default(), diff --git a/apollo-router/src/services/layers/allow_only_http_post_mutations.rs b/apollo-router/src/services/layers/allow_only_http_post_mutations.rs index af7c9e24e2..115a7ce07a 100644 --- a/apollo-router/src/services/layers/allow_only_http_post_mutations.rs +++ b/apollo-router/src/services/layers/allow_only_http_post_mutations.rs @@ -84,9 +84,7 @@ mod forbid_http_get_mutations_tests { .times(1) .returning(move |_| Ok(ExecutionResponse::fake_builder().build())); - let mock = mock_service.build(); - - let mut service_stack = AllowOnlyHttpPostMutationsLayer::default().layer(mock); + let mut service_stack = AllowOnlyHttpPostMutationsLayer::default().layer(mock_service); let http_post_query_plan_request = create_request(Method::POST, OperationKind::Query); @@ -109,9 +107,7 @@ mod forbid_http_get_mutations_tests { .times(1) .returning(move |_| Ok(ExecutionResponse::fake_builder().build())); - let mock = mock_service.build(); - - let mut service_stack = AllowOnlyHttpPostMutationsLayer::default().layer(mock); + let mut service_stack = AllowOnlyHttpPostMutationsLayer::default().layer(mock_service); let http_post_query_plan_request = create_request(Method::POST, OperationKind::Mutation); @@ -134,9 +130,7 @@ mod forbid_http_get_mutations_tests { .times(1) .returning(move |_| Ok(ExecutionResponse::fake_builder().build())); - let mock = mock_service.build(); - - let mut service_stack = AllowOnlyHttpPostMutationsLayer::default().layer(mock); + let mut service_stack = AllowOnlyHttpPostMutationsLayer::default().layer(mock_service); let http_post_query_plan_request = create_request(Method::GET, OperationKind::Query); @@ -161,8 +155,8 @@ mod forbid_http_get_mutations_tests { let expected_status = StatusCode::METHOD_NOT_ALLOWED; let expected_allow_header = "POST"; - let mock = MockExecutionService::new().build(); - let mut service_stack = AllowOnlyHttpPostMutationsLayer::default().layer(mock); + let mut service_stack = + AllowOnlyHttpPostMutationsLayer::default().layer(MockExecutionService::new()); let forbidden_requests = [ Method::GET, diff --git a/apollo-router/src/services/layers/apq.rs b/apollo-router/src/services/layers/apq.rs index 520d4173ce..1cff8a77d6 100644 --- a/apollo-router/src/services/layers/apq.rs +++ b/apollo-router/src/services/layers/apq.rs @@ -229,10 +229,8 @@ mod apq_tests { .expect("expecting valid request")) }); - let mock = mock_service.build(); - let apq = APQLayer::with_cache(DeduplicatingCache::new().await); - let mut service_stack = apq.layer(mock); + let mut service_stack = apq.layer(mock_service); let extensions = HashMap::from([( "persistedQuery".to_string(), @@ -296,36 +294,31 @@ mod apq_tests { .unwrap(), }; - let mut mock_service_builder = MockRouterService::new(); + let mut mock_service = MockRouterService::new(); // the first one should have lead to an APQ error // claiming the server doesn't have a query string for a given hash // it should have not been forwarded to our mock service // the second one should have the right APQ header and the full query string - mock_service_builder - .expect_call() - .times(1) - .returning(move |req| { - let body = req.originating_request.body(); - let as_json = body.extensions.get("persistedQuery").unwrap(); + mock_service.expect_call().times(1).returning(move |req| { + let body = req.originating_request.body(); + let as_json = body.extensions.get("persistedQuery").unwrap(); - let persisted_query: PersistedQuery = - serde_json_bytes::from_value(as_json.clone()).unwrap(); + let persisted_query: PersistedQuery = + serde_json_bytes::from_value(as_json.clone()).unwrap(); - assert_eq!(persisted_query.sha256hash, hash2); + assert_eq!(persisted_query.sha256hash, hash2); - assert!(body.query.is_some()); + assert!(body.query.is_some()); - Ok(RouterResponse::fake_builder() - .build() - .expect("expecting valid request")) - }); + Ok(RouterResponse::fake_builder() + .build() + .expect("expecting valid request")) + }); // the last call should be an APQ error. // the provided hash was wrong, so the query wasn't inserted into the cache. - let mock_service = mock_service_builder.build(); - let apq = APQLayer::with_cache(DeduplicatingCache::new().await); let mut service_stack = apq.layer(mock_service); diff --git a/apollo-router/src/services/layers/ensure_query_presence.rs b/apollo-router/src/services/layers/ensure_query_presence.rs index c1fb20271e..10783f3880 100644 --- a/apollo-router/src/services/layers/ensure_query_presence.rs +++ b/apollo-router/src/services/layers/ensure_query_presence.rs @@ -74,8 +74,7 @@ mod ensure_query_presence_tests { .expect("expecting valid request")) }); - let mock = mock_service.build(); - let service_stack = EnsureQueryPresence::default().layer(mock); + let service_stack = EnsureQueryPresence::default().layer(mock_service); let request: crate::RouterRequest = RouterRequest::fake_builder() .query("{__typename}".to_string()) @@ -89,10 +88,7 @@ mod ensure_query_presence_tests { async fn it_fails_on_empty_query() { let expected_error = "Must provide query string."; - let mock_service = MockRouterService::new(); - let mock = mock_service.build(); - - let service_stack = EnsureQueryPresence::default().layer(mock); + let service_stack = EnsureQueryPresence::default().layer(MockRouterService::new()); let request: crate::RouterRequest = RouterRequest::fake_builder() .query("".to_string()) @@ -115,9 +111,7 @@ mod ensure_query_presence_tests { async fn it_fails_on_no_query() { let expected_error = "Must provide query string."; - let mock_service = MockRouterService::new(); - let mock = mock_service.build(); - let service_stack = EnsureQueryPresence::default().layer(mock); + let service_stack = EnsureQueryPresence::default().layer(MockRouterService::new()); let request: crate::RouterRequest = RouterRequest::fake_builder() .build() diff --git a/examples/add-timestamp-header/src/main.rs b/examples/add-timestamp-header/src/main.rs index d8ae701afd..a48b84af18 100644 --- a/examples/add-timestamp-header/src/main.rs +++ b/examples/add-timestamp-header/src/main.rs @@ -25,13 +25,14 @@ mod tests { #[tokio::test] async fn test_router_service_adds_timestamp_header() { // create a mock service we will use to test our plugin - let mut mock = test::MockRouterService::new(); + let mut mock_service = test::MockRouterService::new(); // The expected reply is going to be JSON returned in the RouterResponse { data } section. let expected_mock_response_data = "response created within the mock"; // Let's set up our mock to make sure it will be called once - mock.expect_call() + mock_service + .expect_call() .once() .returning(move |req: RouterRequest| { // Preserve our context from request to response @@ -42,9 +43,6 @@ mod tests { .unwrap()) }); - // The mock has been set up, we can now build a service from it - let mock_service = mock.build(); - let conf: Conf = serde_json::from_value(serde_json::json!({ "scripts": "src", "main": "add_timestamp_header.rhai", diff --git a/examples/async-auth/src/allow_client_id_from_file.rs b/examples/async-auth/src/allow_client_id_from_file.rs index baf817581f..c2c4d24c45 100644 --- a/examples/async-auth/src/allow_client_id_from_file.rs +++ b/examples/async-auth/src/allow_client_id_from_file.rs @@ -212,7 +212,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know AllowClientIdFromFile did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // In this service_stack, AllowClientIdFromFile is `decorating` or `wrapping` our mock_service. let init = PluginInit::new( @@ -256,7 +256,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know AllowClientIdFromFile did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // In this service_stack, AllowClientIdFromFile is `decorating` or `wrapping` our mock_service. let init = PluginInit::new( @@ -300,13 +300,14 @@ mod tests { let valid_client_id = "jeremy"; // create a mock service we will use to test our plugin - let mut mock = test::MockRouterService::new(); + let mut mock_service = test::MockRouterService::new(); // The expected reply is going to be JSON returned in the RouterResponse { data } section. let expected_mock_response_data = "response created within the mock"; // Let's set up our mock to make sure it will be called once, with the expected operation_name - mock.expect_call() + mock_service + .expect_call() .times(1) .returning(move |req: RouterRequest| { assert_eq!( @@ -327,9 +328,6 @@ mod tests { .unwrap()) }); - // The mock has been set up, we can now build a service from it - let mock_service = mock.build(); - // In this service_stack, AllowClientIdFromFile is `decorating` or `wrapping` our mock_service. let init = PluginInit::new( AllowClientIdConfig { diff --git a/examples/cookies-to-headers/src/main.rs b/examples/cookies-to-headers/src/main.rs index 52acbc29f9..16609d7287 100644 --- a/examples/cookies-to-headers/src/main.rs +++ b/examples/cookies-to-headers/src/main.rs @@ -48,13 +48,14 @@ mod tests { #[tokio::test] async fn test_subgraph_processes_cookies() { // create a mock service we will use to test our plugin - let mut mock = test::MockSubgraphService::new(); + let mut mock_service = test::MockSubgraphService::new(); // The expected reply is going to be JSON returned in the SubgraphResponse { data } section. let expected_mock_response_data = "response created within the mock"; // Let's set up our mock to make sure it will be called once - mock.expect_call() + mock_service + .expect_call() .once() .returning(move |req: SubgraphRequest| { // Let's make sure our request contains our new headers @@ -77,9 +78,6 @@ mod tests { .build()) }); - // The mock has been set up, we can now build a service from it - let mock_service = mock.build(); - let conf: Conf = serde_json::from_value(serde_json::json!({ "scripts": "src", "main": "cookies_to_headers.rhai", diff --git a/examples/forbid-anonymous-operations/src/forbid_anonymous_operations.rs b/examples/forbid-anonymous-operations/src/forbid_anonymous_operations.rs index 4be22912ef..a3d190fff9 100644 --- a/examples/forbid-anonymous-operations/src/forbid_anonymous_operations.rs +++ b/examples/forbid-anonymous-operations/src/forbid_anonymous_operations.rs @@ -127,7 +127,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know ForbidAnonymousOperations did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // In this service_stack, ForbidAnonymousOperations is `decorating` or `wrapping` our mock_service. let service_stack = @@ -162,7 +162,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know ForbidAnonymousOperations did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // In this service_stack, ForbidAnonymousOperations is `decorating` or `wrapping` our mock_service. let service_stack = @@ -197,13 +197,14 @@ mod tests { let operation_name = "validOperationName"; // create a mock service we will use to test our plugin - let mut mock = test::MockRouterService::new(); + let mut mock_service = test::MockRouterService::new(); // The expected reply is going to be JSON returned in the RouterResponse { data } section. let expected_mock_response_data = "response created within the mock"; // Let's set up our mock to make sure it will be called once, with the expected operation_name - mock.expect_call() + mock_service + .expect_call() .times(1) .returning(move |req: RouterRequest| { assert_eq!( @@ -223,9 +224,6 @@ mod tests { .unwrap()) }); - // The mock has been set up, we can now build a service from it - let mock_service = mock.build(); - // In this service_stack, ForbidAnonymousOperations is `decorating` or `wrapping` our mock_service. let service_stack = ForbidAnonymousOperations::default().router_service(mock_service.boxed()); diff --git a/examples/jwt-auth/src/jwt.rs b/examples/jwt-auth/src/jwt.rs index dcd22fdfca..998e553fb7 100644 --- a/examples/jwt-auth/src/jwt.rs +++ b/examples/jwt-auth/src/jwt.rs @@ -418,7 +418,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know JwtAuth did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // In this service_stack, JwtAuth is `decorating` or `wrapping` our mock_service. let service_stack = JwtAuth::default().router_service(mock_service.boxed()); @@ -452,7 +452,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know JwtAuth did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // In this service_stack, JwtAuth is `decorating` or `wrapping` our mock_service. let service_stack = JwtAuth::default().router_service(mock_service.boxed()); @@ -487,7 +487,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know JwtAuth did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // In this service_stack, JwtAuth is `decorating` or `wrapping` our mock_service. let service_stack = JwtAuth::default().router_service(mock_service.boxed()); @@ -522,7 +522,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know JwtAuth did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // In this service_stack, JwtAuth is `decorating` or `wrapping` our mock_service. let service_stack = JwtAuth::default().router_service(mock_service.boxed()); @@ -558,13 +558,14 @@ mod tests { #[tokio::test] async fn test_hmac_jwtauth_accepts_valid_tokens() { // create a mock service we will use to test our plugin - let mut mock = test::MockRouterService::new(); + let mut mock_service = test::MockRouterService::new(); // The expected reply is going to be JSON returned in the RouterResponse { data } section. let expected_mock_response_data = "response created within the mock"; // Let's set up our mock to make sure it will be called once - mock.expect_call() + mock_service + .expect_call() .once() .returning(move |req: RouterRequest| { // Let's make sure our request contains (some of) our JWTClaims @@ -583,9 +584,6 @@ mod tests { .expect("expecting valid request")) }); - // The mock has been set up, we can now build a service from it - let mock_service = mock.build(); - // Create valid configuration for testing HMAC algorithm HS256 let key = "629709bdc3bd794312ccc3a1c47beb03ac7310bc02d32d4587e59b5ad81c99ba"; let conf: Conf = serde_json::from_value(serde_json::json!({ @@ -641,7 +639,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know JwtAuth did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // Create valid configuration for testing HMAC algorithm HS256 let key = "629709bdc3bd794312ccc3a1c47beb03ac7310bc02d32d4587e59b5ad81c99ba"; @@ -693,7 +691,7 @@ mod tests { // It does not have any behavior, because we do not expect it to be called. // If it is called, the test will panic, // letting us know JwtAuth did not behave as expected. - let mock_service = test::MockRouterService::new().build(); + let mock_service = test::MockRouterService::new(); // Create valid configuration for testing HMAC algorithm HS256 let key = "629709bdc3bd794312ccc3a1c47beb03ac7310bc02d32d4587e59b5ad81c99ba"; diff --git a/examples/op-name-to-header/src/main.rs b/examples/op-name-to-header/src/main.rs index 22f8bde11b..3634d27ca9 100644 --- a/examples/op-name-to-header/src/main.rs +++ b/examples/op-name-to-header/src/main.rs @@ -25,13 +25,14 @@ mod tests { #[tokio::test] async fn test_subgraph_processes_operation_name() { // create a mock service we will use to test our plugin - let mut mock = test::MockRouterService::new(); + let mut mock_service = test::MockRouterService::new(); // The expected reply is going to be JSON returned in the RouterResponse { data } section. let expected_mock_response_data = "response created within the mock"; // Let's set up our mock to make sure it will be called once - mock.expect_call() + mock_service + .expect_call() .once() .returning(move |req: RouterRequest| { // Let's make sure our request contains our new header @@ -48,9 +49,6 @@ mod tests { .unwrap()) }); - // The mock has been set up, we can now build a service from it - let mock_service = mock.build(); - let conf: Conf = serde_json::from_value(serde_json::json!({ "scripts": "src", "main": "op_name_to_header.rhai", diff --git a/examples/rhai-logging/src/main.rs b/examples/rhai-logging/src/main.rs index e0e5d24d3e..6f9c0c4a38 100644 --- a/examples/rhai-logging/src/main.rs +++ b/examples/rhai-logging/src/main.rs @@ -26,13 +26,14 @@ mod tests { #[tokio::test] async fn test_subgraph_processes_operation_name() { // create a mock service we will use to test our plugin - let mut mock = test::MockRouterService::new(); + let mut mock_service = test::MockRouterService::new(); // The expected reply is going to be JSON returned in the RouterResponse { data } section. let expected_mock_response_data = "response created within the mock"; // Let's set up our mock to make sure it will be called once - mock.expect_call() + mock_service + .expect_call() .once() .returning(move |_req: RouterRequest| { Ok(RouterResponse::fake_builder() @@ -41,9 +42,6 @@ mod tests { .unwrap()) }); - // The mock has been set up, we can now build a service from it - let mock_service = mock.build(); - let conf: Conf = serde_json::from_value(serde_json::json!({ "scripts": "src", "main": "rhai_logging.rhai", diff --git a/examples/status-code-propagation/src/propagate_status_code.rs b/examples/status-code-propagation/src/propagate_status_code.rs index fa05711663..c164c2ef7c 100644 --- a/examples/status-code-propagation/src/propagate_status_code.rs +++ b/examples/status-code-propagation/src/propagate_status_code.rs @@ -146,8 +146,6 @@ mod tests { .build()) }); - let mock_service = mock_service.build(); - // In this service_stack, PropagateStatusCode is `decorating` or `wrapping` our mock_service. let init = PluginInit::new( PropagateStatusCodeConfig { @@ -185,8 +183,6 @@ mod tests { .build()) }); - let mock_service = mock_service.build(); - // In this service_stack, PropagateStatusCode is `decorating` or `wrapping` our mock_service. let init = PluginInit::new( PropagateStatusCodeConfig { @@ -235,8 +231,6 @@ mod tests { .unwrap()) }); - let mock_service = mock_service.build(); - // StatusCode::INTERNAL_SERVER_ERROR should have precedence here let init = PluginInit::new( PropagateStatusCodeConfig { @@ -279,8 +273,6 @@ mod tests { .unwrap()) }); - let mock_service = mock_service.build(); - // In this service_stack, PropagateStatusCode is `decorating` or `wrapping` our mock_service. let init = PluginInit::new( PropagateStatusCodeConfig { diff --git a/licenses.html b/licenses.html index e357b4d51a..c870860551 100644 --- a/licenses.html +++ b/licenses.html @@ -12332,7 +12332,6 @@

Used by:

  • tower
  • tower-layer
  • tower-service
  • -
  • tower-test
  • Copyright (c) 2019 Tower Contributors
     
    @@ -12398,7 +12397,6 @@ 

    Used by:

    MIT License

    Used by:

    Copyright (c) 2021 Tokio Contributors