如何在自动化测试中后台运行Tonic服务器并正确启停?
Tonic框架自动化测试:后台启动服务器并完成测试
我正在学习Tonic框架,想要编写一个自动化测试:在后台启动Tonic服务器,通过生成的客户端调用接口,测试完成后停止服务器。
尝试方案
当前代码如下:
//... pub fn build(inv: impl Inventory) -> Result<Router, Box<dyn Error>> { let reflection_service = tonic_reflection::server::Builder::configure() .register_encoded_file_descriptor_set(FILE_DESCRIPTOR_SET) .build()?; let srv = Server::builder() .add_service(InventoryServer::new(inv)) .add_service(reflection_service); Ok(srv) } #[tokio::test] async fn works() -> Result<(), Box<dyn Error>> { let addr = "127.0.0.1:9001".parse()?; let inventory = InMemoryInventory::default(); let (handle, registration) = AbortHandle::new_pair(); _ = Abortable::new(build(inventory)?.serve(addr), registration); // 服务器未启动 let sku = "test".to_string(); let add_res = add::add(AddOptions { sku: sku.clone(), price: 0.0, quantity: 0, name: None, description: None }).await?; println!("{:?}", add_res); let get_res = get::get(GetOptions { sku }).await?; println!("{:?}", get_res); handle.abort(); Ok(()) }
我知道问题在于serve的future未被触发,导致服务器无法启动;如果添加await,服务器会在当前线程启动并阻塞线程。
我尝试用tokio::spawn创建新任务:
_ = Abortable::new(tokio::spawn(async move { let addr = "127.0.0.1:9001".parse().unwrap(); let inventory = InMemoryInventory::default(); build(inventory).unwrap().serve(addr).await }), registration);
但出现如下错误:
error: future cannot be sent between threads safely --> svc-store/src/main.rs:36:37 | 36 | _ = Abortable::new(tokio::spawn(async move { | _____________________________________^ 37 | | let addr = "127.0.0.1:9001".parse().unwrap(); 38 | | let inventory = InMemoryInventory::default(); 39 | | build(inventory).unwrap().serve(addr).await 40 | | }), registration); | |_____^ future created by async block is not `Send` | = help: the trait `std::marker::Send` is not implemented for `dyn std::error::Error`
我仅需要启动一个可安全存储依赖的后台任务,无需线程间通信,现提出两个问题:
- 实现需求的最简方式是什么?
- 为何第二种方案不符合Go程序员的预期?
内容的提问来源于stack exchange,提问作者bart-kosmala
相关产品推荐
相关产品推荐

