【问题标题】:Rust doc test with async function #[tokio-test]使用异步函数的 Rust 文档测试#[tokio-test]
【发布时间】:2021-02-10 13:19:57
【问题描述】:

似乎不能在 Rust doc 测试中使用 #[tokio-test] 来测试异步函数?

现在我必须编写一个异步主函数并用#[tokio-main] 标记它并在其中调用test_fn().await 以让一些异步函数在cargo test --doc 期间运行。

还有其他更好的方法可以让文档测试像普通测试函数一样运行,例如使用#[tokio-test]?如果标签#[tokio-test] 可以显示在文档中也很好,这样用户可以复制文档并直接在他们的项目中使用它作为测试。 (这可能可以像##[tokio-test]一样完成?)

【问题讨论】:

    标签: rust rust-cargo rust-tokio


    【解决方案1】:

    Doc 测试自动将代码块包装在 同步 fn main() { … } 中。 .awaiting 需要 异步 运行时。你不能.await 不产生某种运行时。您可以为每个文档测试生成一个常规的多线程运行时:

    /// ```rust
    /// #[tokio::main]
    /// async fn main() {
    ///    let len = async { "aaaa".len() }.await;
    ///    assert_eq!(len, 4);
    /// }
    /// ```
    

    为每个文档测试生成一个运行时可能不是最好的主意。更好的方法是使用tokio_test::block_on,它使用测试本地运行时(类似于#[tokio-test])来阻止提供的未来:

    /// ```rust
    /// let len = tokio_test::block_on( async { "aaaa".len() } );
    /// assert_eq!(len, 4);
    /// ```
    

    要减少样板,您可以为block_on 创建一个宏:

    macro_rules! bo {
      ($e:expr) => {
        tokio_test::block_on($e)
      };
    }
    

    然后像这样使用它:

    /// ```rust
    /// let len = async { "aaaa".len() };
    /// assert_eq!(bo!(len), 4)
    /// ```
    

    【讨论】:

    • 谢谢。我遇到的问题是我想使用 doc 来展示如何使用 #[tokio-test] 编写异步代码测试。但是如果#[tokio-test] 不能与doc 一起使用,那么我可能无法编写一个可以显示如何使用#[tokio-test] 并且还可以在货物测试期间运行doc 的代码的doc。
    【解决方案2】:

    如果您想在 doctests 中使用异步代码而不为每个代码生成新的运行时,您可以将整个 doctest 包装起来,而不仅仅是 tokio_test::block_on 中的异步部分。

    例子:

    /// Asynchronously get length of "aaaa"
    /// ```
    /// # tokio_test::block_on(async {
    ///   let len = async { "aaaa".len() };
    ///   assert_eq!(len.await, 4)
    /// # })
    /// ```
    

    【讨论】:

    • 谢谢。这似乎是一个很好的解决方案。
    • 请注意,在tokio_test::block_on()的当前(0.4.2)版本中,这将创建一个新的运行时,因此它大致相当于# tokio::runtime::Handle::new().unwrap().block_on(async {
    • 这与我的回答有何不同?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-02-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-11-10
    • 1970-01-01
    • 2012-08-22
    相关资源
    最近更新 更多