You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在使用NEAR Workspaces-rs的Rust集成测试中查看日志并初始化日志记录器

解决NEAR workspaces-rs集成测试中看不到合约日志的问题

我明白你遇到的困境——用NEAR的workspaces-rs写集成测试时,合约里的日志死活出不来,哪怕试了env_logger的测试初始化也只看到测试代码自己的日志。这其实是因为NEAR合约的日志体系和普通Rust程序的日志不是一回事,咱们得换个思路处理:


核心原因:两类日志的本质区别

你在合约里用的log!(NEAR SDK提供的)或者换成的info!(Rust标准log crate),和测试代码里的日志走的是完全不同的路径:

  • NEAR SDK的log!是直接调用NEAR区块链的环境API(env::log_str),这些日志会被workspaces-rs的沙箱/测试网环境捕获,但默认不会自动输出到终端。
  • 如果你换成Rust标准log的info!,合约编译成Wasm后,log crate默认没有输出目标,自然也看不到任何日志。

方案1:继续用NEAR SDK的log!(推荐)

这是最简单的方式,只需要让workspaces-rs把捕获到的合约日志输出出来:

步骤1:在测试代码中正确初始化日志

确保你的测试里初始化env_logger时,包含workspaces-rs的日志级别(因为workspaces会把合约日志以info级别输出):

#[cfg(test)]
mod tests {
    use workspaces::prelude::*;
    use log::info;

    fn init_test_logger() {
        // 初始化env_logger,设置日志级别为Info,适配测试环境
        let _ = env_logger::builder()
            .filter_level(log::LevelFilter::Info)
            .is_test(true)
            .try_init();
    }

    #[tokio::test]
    async fn test_remove_function() {
        init_test_logger();
        
        // 创建沙箱环境
        let worker = workspaces::sandbox().await.unwrap();
        // 部署合约(这里假设你已经有合约字节码的处理逻辑)
        let contract = worker.dev_deploy(include_bytes!("../target/wasm32-unknown-unknown/release/your_contract.wasm"))
            .await.unwrap();

        // 调用合约的remove方法
        let result = contract.call(&worker, "remove")
            .args_json(serde_json::json!({
                "key": "test_key",
                "recipient": "test_account.near"
            }))
            .transact()
            .await.unwrap();

        // 你也可以直接从执行结果中手动取出日志打印
        println!("合约执行日志: {:?}", result.logs());
    }
}

步骤2:运行测试时配置环境变量

在终端运行测试时,需要设置RUST_LOG环境变量,让workspaces-rs输出合约日志:

RUST_LOG=workspaces=info cargo test -- --nocapture
  • RUST_LOG=workspaces=info:告诉env_logger输出workspaces-rs的info级别日志(合约日志就在这里面)
  • --nocapture:禁止Rust测试框架捕获输出,让日志实时显示在终端(如果不需要实时,也可以不加,测试结束后会显示所有日志)

方案2:用Rust标准log crate的info!等宏

如果你更习惯用标准log的宏,需要在合约里把日志转发到NEAR的环境日志API,这样workspaces-rs才能捕获到:

步骤1:在合约中实现自定义Logger

在你的合约代码里添加一个简单的Logger,把log crate的日志转发到env::log_str:

use near_sdk::{env, near_bindgen};
use log::{Level, LevelFilter, Metadata, Record};

// 自定义Logger,把log crate的日志转发到NEAR环境日志
struct NearEnvLogger;

impl log::Log for NearEnvLogger {
    fn enabled(&self, metadata: &Metadata) -> bool {
        // 这里可以设置你想要的日志级别
        metadata.level() <= Level::Info
    }

    fn log(&self, record: &Record) {
        if self.enabled(record.metadata()) {
            // 格式化日志并调用NEAR的环境日志API
            env::log_str(&format!("[{}] {}", record.level(), record.args()));
        }
    }

    fn flush(&self) {}
}

#[near_bindgen]
#[derive(Default)]
pub struct Contract;

#[near_bindgen]
impl Contract {
    #[init]
    pub fn new() -> Self {
        // 初始化log crate的Logger
        log::set_logger(&NearEnvLogger).unwrap();
        log::set_max_level(LevelFilter::Info);
        Self::default()
    }

    pub fn remove(&mut self, key: String, recipient: String) {
        // 现在可以用标准log的info!宏了
        info!("Removed {} from {}", &key, &recipient);
        // 你的业务逻辑...
    }
}

步骤2:测试端配置和方案1一样

按照方案1的测试代码初始化日志,然后用同样的命令运行测试,就能看到标准log宏输出的日志了。


常见排查点

  • 确保你的合约部署和调用逻辑正确,如果合约没执行到对应的日志代码,自然看不到输出。
  • 检查RUST_LOG的设置是否正确,比如如果用了debug级别,可以改成RUST_LOG=workspaces=debug看更详细的日志。
  • 确认测试函数用了#[tokio::test],因为workspaces-rs是基于tokio异步运行时的。

内容的提问来源于stack exchange,提问作者Ryan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.27 16:52:33