2021-12-02 20:09 | 出处: CUDOS
去中心化云计算网络CUDOS是一个第一层区块链,由智能合约管理,能够以分布式的方式将区块链与安全的外部资源对接,为区块链引入高性能计算以及解决区块链可扩展问题。在这一系列文章中,我们将从基础知识入手,逐步讲解如何在CUDOS网络上搭建智能合约。
CUDOS的测试网激励计划正在进行中,感兴趣的开发者可以参与到测试其公测网络Somniorum的过程中,并赢得相应的奖励。
在第一部分中,您完成了CosmWasm环境和CosmWasm合约架构的设置。在第二部分中,我们讨论了设置项目的过程。在第三部分中,我们讨论了主要的业务逻辑以及用于计算和将值存储于state(状态)中的函数。
在本系列的第四篇也是最后一篇文章中,我们将进行单元和集成测试,过程中会用到我们迄今为止所学到的所有知识。此外,我们还将尝试一些函数,以评估我们对整个流程的理解程度。
Rust提供了一个很好的功能,可以让你在一个项目中进行所有的单元和集成测试。通过这种方式,你不需要为测试设置另一个环境。
#[cfg(test)]
mod tests {
use super::*;
usecosmwasm_std::testing::{mock_dependencies, mock_env, mock_info};
use cosmwasm_std::{coins,StdError};
…..
}
l Use super::* 将导入本项目中使用的所有libs
l usecosmwasm_std::testing::{mock_dependencies, mock_env, mock_info}:在这里你会得到测试所需的deps、env和info的模拟。
l 让我们直接进入测试阶段
A. 首先,创建一个能够为我们成功部署合约的函数,所以你需要一个能够为你部署合约的函数do_instantiate。
B. Params(参数):
C.这里你需要一个InstantiateMsg。
D.之后,你需要模拟将合约实例化的调用者,所以为此,使用mock_info,将所有者(owner)作为第一个参数。如果你需要传递一些原生代币,你必须插入一个Coins数组作为第二个参数。
E.我已经使用mock_env来模拟区块链信息,如区块高度、时间等。
F.我调用了带有所有参数的实例化函数。
G.我设定响应长度为0,因为Response::default()将给出零长度的响应对象。
H.调用query_token_info()来确认合约上的数据存储。
I.调用getBalance()来检查接收人是否得到了初始余额。
J.调用query_minter来验证合约的所有者是否是铸币者。
fn do_instantiate(
mut deps: DepsMut,
addr: &str,
amount: Uint128,
owner: &str,
) ->TokenInfoResponse {
let instantiate_msg= InstantiateMsg {
name: “Auto Gen”.to_string(),
symbol: “****”.to_string(),
decimals: 3,
initial_balances:vec![Cw20Coin {
address:addr.to_string(),
amount,
}],
};
let info =mock_info(owner, &[]);
let env =mock_env();
let res =instantiate(deps.branch(), env, info, instantiate_msg).unwrap();
assert_eq!(0, res.messages.len());
let meta =query_token_info(deps.as_ref()).unwrap();
assert_eq!(
meta,
TokenInfoResponse {
name: “Auto Gen”.to_string(),
symbol: “****”.to_string(),
decimals: 3,
total_supply:amount,
}
);
assert_eq!(get_balance(deps.as_ref(),addr), amount);
assert_eq!(query_minter(deps.as_ref()).unwrap(),owner);
meta
}
A.can_mint_by_minter测试用例确保了只有铸币者可以向其他地址铸造新的代币。
B. 让我们直接进入测试用例。
C. 在Rust中,要将任何函数标记为测试用例,你需要在该函数的顶部添加#[test]。
D. 一般来说,开发人员会在同一个测试用例中写下与一个给定函数相关的所有正面和负面测试用例。所以你必须使用注释(//)来隔离测试用例。
E. 首先,你必须模拟deps对象,因为它包含了区块链提供的存储、API和查询器;这是用mock_dependencies()完成的。
F. 然后创建几个变量,用于:
i. Recipient(接收人):谁将接收到作为初始余额的代币
ii. Amount(金额):接收人收到多少代币作为初始余额
iii. Owner(所有者):地址,其部署了合约并成为了铸币者
iv. Winner(获胜者):地址,铸币者将向其铸造代币
v. Prize(奖励):所有者将向获胜者铸造的CW20代币的数量
G. 第一个测试用例:所有者成功铸造代币给获胜者
i. 为了调用Mint函数,你需要创建一个ExecuteMsg::Mint对象。
ii. 调用mock_info来把调用者模拟成所有者地址。
iii. 调用mock_env来模拟区块链。
iv. 使用execute方法来运行第一步创建的executeMsg,当它收到None时,做unwrap返回一个panic。
v. 使用getBalance()检查Winner(获胜者)的余额。如果余额等于奖励(prize),那么我们的Mint函数就算用对了。
H. 第二个测试用例:其他人不能铸币
i. 为了调用Mint函数,你需要创建一个ExecuteMsg::Mint对象。
ii. 调用mock_info来模拟其他人的地址。为此,使用“anyone else(其他任何人)”作为调用者。
iii. 调用mock_env来模拟区块链。
iv. 使用execute方法来运行第一步创建的executeMsg,并做unwrap_err返回一个错误信息。
v. 设定从函数收到的错误信息为ContractError:Unauthorized。
I. 第三个测试用例:当把零传递为一个金额(amount)时抛出错误
i. 为了调用Mint函数,你需要创建一个ExecuteMsg::Mint对象,其金额为0。
ii. 调用mock_info来把所有者(owner)模拟为调用者。
iii. 调用mock_env来模拟区块链。
iv. 使用execute方法来运行第一步创建的executeMsg,并做unwrap_err返回一个错误信息。
v. 设定从函数收到的错误信息为ContractError::InvalidZeroAmount。
#[test]
fn can_mint_by_minter(){
let mut deps =mock_dependencies(&[]);
let recipient =String::from(“recipient”);
let amount =Uint128::new(11223344);
let owner =String::from(“asmodat”);
do_instantiate(deps.as_mut(),&recipient, amount, &owner);
let winner = String::from(“lucky”);
let prize =Uint128::new(222_222_222);
let msg =ExecuteMsg::Mint {
recipient:winner.clone(),
amount: prize,
};
// successfulminting of tokens to winner by owner
let info =mock_info(owner.as_ref(), &[]);
let env =mock_env();
let res =execute(deps.as_mut(), env, info, msg).unwrap();
assert_eq!(0,res.messages.len());
assert_eq!(get_balance(deps.as_ref(),recipient), amount);
assert_eq!(get_balance(deps.as_ref(),winner.clone()), prize);
// Others cannotmint
let msg =ExecuteMsg::Mint {
recipient:String::from(“lucky”),
amount:Uint128::new(222),
};
let info =mock_info(“anyone else”, &[]);
let env =mock_env();
let err =execute(deps.as_mut(), env, info, msg).unwrap_err();
assert_eq!(err, ContractError::Unauthorized{});
// throw error aspass zero as an amount
let msg =ExecuteMsg::Mint {
recipient:winner.clone(),
amount:Uint128::zero(),
};
let info =mock_info(owner.as_ref(), &[]);
let env =mock_env();
let err =execute(deps.as_mut(), env, info, msg).unwrap_err();
assert_eq!(err,ContractError::InvalidZeroAmount {});
}
现在,我希望你们以上述代码和CW-plus为例,尝试创建一些函数:
通过以下链接,您可以立即加入我们的测试网奖励计划Project Artemis:
加入CUDOS的Discord服务器
加入CUDOS的Telegram社区
买入CUDOS
成为CUDOS的大使
值得注意的是,您将根据您在测试网中完成的任务获得奖励。
此外,如果您已经购买了CUDOS代币,可以把它们质押在我们的平台上,以确保网络安全,作为回报,您可以获得奖励。
CUDOS网络是一个第一层区块链和第二层计算及预言机网络,旨在大规模提供去中心化、无许可的高性能计算,可将计算资源扩展至数十万节点。在与以/太坊、Algorand、波卡和Cosmos桥接后,CUDOS将在所有桥接的区块链上实现可扩展的计算和第二层预言机。
官网:https://www.cudos.org/
Twitter:https://twitter.com/CUDOS_
Discord:https://discord.gg/VnkutnU3
微博:https://weibo.com/cudos
中文电报:https://t.me/Cudos2021