Skip to content

Latest commit

 

History

History
137 lines (94 loc) · 5.78 KB

06.md

File metadata and controls

137 lines (94 loc) · 5.78 KB
title actions requireLogin material
保持游戏趣味性
checkAnswer
hints
true
editor
language startingCode answer
javascript
test/CryptoZombies.js
const CryptoZombies = artifacts.require("CryptoZombies"); const zombieNames = ["Zombie 1", "Zombie 2"]; contract("CryptoZombies", (accounts) => { let [alice, bob] = accounts; // start here it("should be able to create a new zombie", async () => { const contractInstance = await CryptoZombies.new(); const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice}); assert.equal(result.receipt.status, true); assert.equal(result.logs[0].args.name,zombieNames[0]); }) //define the new it() function })
const CryptoZombies = artifacts.require("CryptoZombies"); const zombieNames = ["Zombie 1", "Zombie 2"]; contract("CryptoZombies", (accounts) => { let [alice, bob] = accounts; let contractInstance; beforeEach(async () => { contractInstance = await CryptoZombies.new(); }); it("should be able to create a new zombie", async () => { const result = await contractInstance.createRandomZombie(zombieNames[0], {from: alice}); assert.equal(result.receipt.status, true); assert.equal(result.logs[0].args.name,zombieNames[0]); }) it("should not allow two zombies", async () => { }) })

到目前为止都做得很好!可以确定的是我们的用户会创建新僵尸了👌🏻。

然而,如果他们能够一直调用这个函数,给他们的军队创造无限僵尸,那么游戏就没意思了。因此,在第2课第4章中,我们给 createZombieFunction() 添加了一个 require 语句,以确保每个用户所拥有的僵尸不超过一个:

require(ownerZombieCount[msg.sender] == 0)

让我们来测试下这个特性,看看它是否有效。

hook

🤞短短几分钟后,我们会有不止一个测试,并且每个测试都应该从头开始。因此,对于每个测试,我们都必须创建一个智能合约的新实例,如下所示:

const contractInstance = await CryptoZombies.new();

如果可以只编写一次,然后让 Truffle 在每次测试时自动运行它,岂不是很棒吗?

嗯…… Mocha(和 Truffle)的一个特性是能够在测试之前或之后运行一些称为 hooks 的代码片段。要在执行测试之前运行某个东西,代码应该放在一个名为 beforeEach() 的函数中。

因此,不需要多次编写 contract.new(),只用这样写一次就行:

beforeEach(async () => {
  // let's put here the code that creates a new contract instance
});

然后,Truffle 就会负责一切。有木有很贴心啊?

实战演习

  1. 在初始化 alicebob 的代码行下面,让我们来声明一个名为 contractInstance 的变量。不要把它分配给任何东西。

    注意:我们想要 contractInstance 的作用域仅限于定义它的块。使用 let 代替 var

  2. 接下来,复制/粘贴上面的代码片段,以定义 beforeEach() 函数。

  3. 现在来填充新函数主体。继续并移动beforeEach() 函数中创建新合约实例的代码行。既然我们已经在其他地方定义了 contractInstance,你现在可以删除 const 限定符了。

  4. 我们的测试将需要一个新的 it() 空函数。将测试名(这是传递给 it() 函数的第一个参数)赋值为“should not allow two zombies”。

我们将在下一章继续详细讲解这个函数!


🧟‍♂️这里有…… 各种各样的僵尸! ! !🧟‍♂️

如果你真的真的想达到 精通,请继续往下读。否则…… 直接点击下一步,就可以进入下一章了。

还在吗?😁

太棒了!毕竟,有什么理由拒绝让自己变得更优秀呢?

现在,让我们回头看看 contract.new 是如何运行的。基本上,每次我们调用这个函数时,Truffle 都会确保新合约得以部署。

一方面,这很有用,因为它让我们完全从头开始每个测试。

但另一方面,如果每个人都创建无数个合约,区块链将变得臃肿。我们想要你留下来,不是你的旧测试合同!

我们想要阻止这种情况发生,对吧?

幸好,解决方案非常简单…… 我们的合约一旦不再需要就会selfdestruct(自行销毁)

其原理如下:

  • 首先,我们要添加一个新函数到 CryptoZombies 智能合约,像这样:
function kill() public onlyOwner {
    selfdestruct(owner());
}

Note: If you want to learn more about selfdestruct(), you can read the Solidity docs here. The most important thing to bear in mind is that selfdestruct is the only way for code at a certain address to be removed from the blockchain. This makes it a pretty important feature!

  • n接着,与上面解释过的 beforeEach() 函数有点类似,我们将创建一个名为 afterEach() 的函数:
afterEach(async () => {
    await contractInstance.kill();
});
  • 最后, Truffle 将确保在执行测试之后调用此函数。。

瞧,智能合约自动删除了!

在本课中,我们有很多内容要介绍,实现这个特性可能至少还需要两章。我们相信你能做到。💪🏻