Truffle中JS测试小技巧

solidity是以太坊上首选的智能合约开发语言,有很多人都用它进行智能合约的学习与开发;而truffle是以太坊上最流行的开发框架,深受大家的喜爱。

在开发过程中,不可避免的需要对solidity代码进行测试。因为能够按需定制、灵活、方便的原因,大部分人选择的都是基于JS来书写测试代码,因此以下的小技巧都是基于JS测试中遇到的一些困惑之处,总结一下与大家共勉。

编码风格的选择: .THENASYNC/AWAIT

因为异步执行的关系,truffle中的JS测试有两种编码风格:

  1. .then风格
it("should put 10000 MetaCoin in the first account", function() {
  return MetaCoin.deployed().then(function(instance) {
    return instance.getBalance.call(accounts[0]);
  }).then(function(balance) {
    assert.equal(balance.valueOf(), 10000, "10000 wasn't in the first account");
  });
});
  1. ASYNC/AWAIT风格
it("should put 10000 MetaCoin in the first account", async () => {
   let instance = await MetaCoin.deployed();
   let balance = await instance.getBalance.call(accounts[0]);
   assert.equal(balance.valueOf(), 10000);
})

这两种风格其实执行的测试内容都一样,但明显ASYNC/AWAIT风格的更适合书写以及阅读——更有美感;而且,更重要的是,修改测试代码时更不容易出错(亲测使用.then风格修改时非常痛苦),所以强烈推荐使用ASYNC/AWAIT风格来书写测试代码。

如何测试事件

事件(event)是solidity中用来与前端进行交互的机制,使用的范围很广。但是作为新手时,对于如何测试事件真的是感觉无从下手。

参考库合约openzeppelin中关于测试事件的写法:

function awaitEvent (event, handler) {
    return new Promise((resolve, reject) => {
    function wrappedHandler (...args) {
        Promise.resolve(handler(...args)).then(resolve).catch(reject);
    }
      
    event.watch(wrappedHandler);
    });
}

it("should emit GotPayed", async () => {
    let instance = await PersonalPayment.new();
        
    let event = instance.GotPayed({});
    let watcher = async function (err, result) {
        event.stopWatching();
        if (err) { throw err; }
        assert.equal(result.args._amount, 10);
    };
    await instance.payPayments([accounts[1]], [10], {value: web3.toWei('11', 'ether')});
    await awaitEvent(event, watcher);
})

其基本思路还是web3接口中的方法:

  1. 设置好event
  2. 写好处理的watcher函数,在awaitEvent函数中通过Promise来进行异步处理

不过,在实际的测试中,发现了一份更加精简的方案:

it("should emit GotPayed", async () => {
    let instance = await PersonalPayment.new();
    await instance.payPayments([accounts[1]], [10], {value: web3.toWei('11', 'ether')});
    let event = await new Promise((resolve, reject) => {
        instance.GotPayed((err, log) => {
            if(!err) {resolve(log);}
        })
    });
    assert.equal(event.args._amount, 10);
})

思路上是模拟的与前端进行交互的方式,在这里加了一层基于Promise的异步调用即可。可以看出,在实际中逻辑更简单,代码也更加简洁

如何模拟时间跨度进行测试

在测试中,有时候需要模拟一段时间跨度来测试代码的逻辑,但是在没有教程的情况下,这一步完全是没有思路。我们先上一个例子,再来解读一下:

await web3.currentProvider.send({
    jsonrpc: "2.0", 
    method: "evm_increaseTime", 
    params: [10], 
    id: 0
});
await web3.currentProvider.send({
    jsonrpc: "2.0", 
    method: "evm_mine", 
    params: [], 
    id: 0
});
  1. 通过web3.currentProvider.send方法执行了两条命令:web3.currentProviderweb3接口中的方法,获取当前的网络provider;而接下来的send()则是发起一次RPC调用,输入的是JSON RPC格式的参数来指明要执行的方法:
    • method: "evm_increaseTime:表示执行的方法
    • params: [10]:表示要执行方法的参数
  2. evm_increaseTimeevm_mine皆是来自于Ganache CLI的特有方法:Ganache CLI是开发框架truffle中内置的个人化区块链组件,主要用于模拟以太坊来方便开发、测试与部署;也是当前我们采用的环境。
    • evm_increaseTime:增加区块时间,是我们模拟时间跨度主要需要的功能
    • evm_mine:强制进行一次区块打包,主要是为了让前面执行evm_increaseTime的动作生效

在完成这些操作之后,就可以进行正常的测试逻辑了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 195,783评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,360评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 142,942评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,507评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,324评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,299评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,685评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,358评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,652评论 1 293
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,704评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,465评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,318评论 3 313
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,711评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,991评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,265评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,661评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,864评论 2 335

推荐阅读更多精彩内容