Java开发的智能合约单元测试教程【nba下注】

nba投注网站

在本教程中,我们将构建一个非常简单的合约,为其撰写单元测试,并运营调试过程以查询Bug。运营该示例所需的全部是Java和IDE。

只需创立一个倚赖AVM近期工具库的Java项目作为库。1.撰写智能合约首先创立智能合约。以下是可用作非常简单投票DApp的智能合约的示例。

智能合约的功能:1. 只有合约所有者(部署合约的帐户)可以加到或移除成员。2. 只有会员可以讲解新的议案。3. 只有会员可以对议案展开投票。

4. 如果多达50%的成员赞同该议案并对其投票,该议案将通过。package org.aion.avm.embed.temp;import avm.Blockchain;import org.aion.avm.tooling.abi.Callable;import org.aion.avm.userlib.AionMap;import org.aion.avm.userlib.AionSet;import avm.Address;import org.aion.avm.userlib.abi.ABIDecoder;public class Voting {private static AionSetAddress members = new AionSet();private static AionMapInteger,Proposal proposals = new AionMap();private static Address owner;private static int minimumQuorum;static {ABIDecoder decoder = new ABIDecoder(Blockchain.getData());Address[] arg = decoder.decodeOneAddressArray();for (Address addr : arg) {members.add(addr);}updateQuorum();owner = Blockchain.getCaller();}@Callablepublic static void addProposal(String description) {Address caller = Blockchain.getCaller();Blockchain.require(isMember(caller));Proposal proposal = new Proposal(description, caller);int proposalId = proposals.size();proposals.put(proposalId, proposal);Blockchain.log(“NewProposalAdded”.getBytes(),Integer.toString(proposalId).getBytes(), caller.toByteArray(),description.getBytes());}@Callablepublic static void vote(int proposalId) {Address caller = Blockchain.getCaller();Blockchain.require(isMember(caller)proposals.containsKey(proposalId));Proposal votedProposal = proposals.get(proposalId);votedProposal.voters.add(caller);Blockchain.log(“Voted”.getBytes(),Integer.toString(proposalId).getBytes(), caller.toByteArray());if (!votedProposal.isPassedvotedProposal.voters.size() ==minimumQuorum) {votedProposal.isPassed = true;Blockchain.log(“ProposalPassed”.getBytes(),Integer.toString(proposalId).getBytes());}}@Callablepublic static void addMember(Address newMember) {onlyOwner();members.add(newMember);updateQuorum();Blockchain.log(“MemberAdded”.getBytes(),newMember.toByteArray());}@Callablepublic static void removeMember(Address member) {onlyOwner();members.remove(member);updateQuorum();Blockchain.log(“MemberRemoved”.getBytes(),member.toByteArray());}@Callablepublic static String getProposalDescription(int proposalId) {return proposals.containsKey(proposalId) ?proposals.get(proposalId).description : null;}@Callablepublic static Address getProposalOwner(int proposalId) {return proposals.containsKey(proposalId) ?proposals.get(proposalId).owner : null;}@Callablepublic static boolean hasProposalPassed(int proposalId) {return proposals.containsKey(proposalId) proposals.get(proposalId).isPassed;}@Callablepublic static int getMinimumQuorum() {return minimumQuorum;}@Callablepublic static boolean isMember(Address address) {return members.contains(address);}private static void onlyOwner() {Blockchain.require(owner.equals(Blockchain.getCaller()));}private static void updateQuorum() {minimumQuorum = members.size() / 2 + 1;}private static class Proposal {String description;Address owner;boolean isPassed;AionSetAddress voters = new AionSet();Proposal(String description, Address owner) {this.description = description;this.owner = owner;}}}合约中的static块在部署时仅有继续执行一次。 我们在此块中设置初始成员,minimumQuorum和所有者。尽管我们与一组成员启动了合约,但所有者随后也可以加到和移除成员。

我们用于AionSet和AionMap追踪成员及其议案。可以用于其唯一标识符从地图采访每个建议。智能合约的主要职能是:· addProposal,网卓新闻网,容许成员加到议案解释以展开投票。· vote,容许成员通过传送其ID对能用议案展开投票。

夺得多数成员投票的议案将通过。请注意,将分解ProposalPassed事件以记录已通过投标的ID。2.撰写单元测试我们将用于AvmRule撰写测试。 AvmRule是用作在嵌入式AVM上测试合约的Junit规则。

它创立Aion内核和AVM的内存中回应形式。每次我们运营测试时,都会创下内置的内核和AVM实例。

nba下注官网

在测试我们的合约之前,我们必须将其部署到内存中的Aion区块链中,并且我们将用于AvmRule已完成此任务。A.实例化AvmRule您可以看见该规则包括一个布尔参数,该布尔参数落成/停止使用调试模式。 最差在落成调试器的情况下撰写测试。

nba下注

您可以在下一部分中查阅如何调试合约。@Rulepublic AvmRule avmRule = new AvmRule(true);留意:此行将为每种测试方法实例化嵌入式AVM。

如果将规则定义为@classRule,则将仅有为测试类实例化AVM和内核的一个实例。B.提供合约字节现在,我们必需提供与合约jar的内存回应比较不应的字节。

为了提供字节,我们将用于AvmRule中的getDappBytes方法。getDappBytes使用以下参数:1. 合约的主要类别。2. 合约结构函数参数,可以在静态块中对其展开采访和解码。

3. DApp jar中必须包括其他类。public byte[] getDappBytes(Class? mainClass, byte[] arguments,Class?… otherClasses)C.部署您的智能合约用于部署功能可以精彩已完成智能合约的部署。public ResultWrapper deploy(Address from, BigInteger value,byte[] dappBytes)AvmRule还获取了在Aion内核中创立具备初始余额的帐户的功能。

以下是由3名成员构成的小组部署投票智能合约的方法。public class VotingContractTest {@Rulepublic AvmRule avmRule = new AvmRule(true);public Address dappAddress;public Address owner = avmRule.getPreminedAccount();public Address[] members = new Address[3];@Beforepublic void setup() {for (int i = 0; imembers.length; i++) {// create accounts with initial balancemembers[i] = avmRule.getRandomAddress(BigInteger.valueOf(10_000_000L));}// encode members array as an argumentbyte[] deployArgument = ABIUtil.encodeOneObject(members);// get the bytes representing the in memory jarbyte[] dappBytes = avmRule.getDappBytes(Voting.class, deployArgument);//deploy and get the contract addressdappAddress = avmRule.deploy(owner, BigInteger.ZERO, dappBytes).getDappAddress();}}D.调用方法我们可以通过以下方式调用合约中的方法:1. 编码方法名称及其参数。2. 将编码后的字节传送给AvmRule的call方法。public ResultWrapper call(Address from, Address dappAddress,BigInteger value, byte[] transactionData)例如我们创立一个新的议案。

nba下注官网

我们将通过检查否分解了NewProposalAdded事件以及事件主题和数据准确来检验议案。@Testpublic void addProposalTest() {String description = “new proposal description”;byte[] txData = ABIUtil.encodeMethodArguments(“addProposal”, description);AvmRule.ResultWrapper result = avmRule.call(members[0], dappAddress, BigInteger.ZERO, txData);// assert the transaction was successfulAssert.assertTrue(result.getReceiptStatus().isSuccess());// assert the event is generatedAssert.assertEquals(1, result.getLogs().size());Log log = result.getLogs().get(0);// validate the topics and dataAssert.assertArrayEquals(LogSizeUtils.truncatePadTopic(“NewProposalAdded”.getBytes()), log.copyOfTopics().get(0));Assert.assertArrayEquals(LogSizeUtils.truncatePadTopic(Integer.toString(0).getBytes()), log.copyOfTopics().get(1));Assert.assertArrayEquals(LogSizeUtils.truncatePadTopic(members[0].toByteArray()), log.copyOfTopics().get(2));Assert.assertArrayEquals(description.getBytes(), log.copyOfData());}现在我们将递交一个议案以及两个投票。

由于有两个有所不同的成员以ID 0对议案展开了投票,议案不应通过。因此我们期望为最后一个事务分解两个有所不同的事件-Voted和ProposalPassed。您还可以通过议案ID查找议案的状态。

您不会看见回到的解码数据为true,回应议案已通过。@Testpublic void voteTest() {String description = “new proposal description”;byte[] txData = ABIUtil.encodeMethodArguments(“addProposal”, description);AvmRule.ResultWrapper result = avmRule.call(members[0], dappAddress, BigInteger.ZERO, txData);Assert.assertTrue(result.getReceiptStatus().isSuccess());Assert.assertEquals(1, result.getLogs().size());//vote #1txData = ABIUtil.encodeMethodArguments(“vote”, 0);result = avmRule.call(members[1], dappAddress, BigInteger.ZERO, txData);Assert.assertTrue(result.getReceiptStatus().isSuccess());Assert.assertEquals(1, result.getLogs().size());//vote #2txData = ABIUtil.encodeMethodArguments(“vote”, 0);result = avmRule.call(members[2], dappAddress, BigInteger.ZERO, txData);Assert.assertTrue(result.getReceiptStatus().isSuccess());Assert.assertEquals(2, result.getLogs().size());//validate that the proposal is stored as passedtxData = ABIUtil.encodeMethodArguments(“hasProposalPassed”, 0);result = avmRule.call(members[2], dappAddress, BigInteger.ZERO, txData);//decode the return data as booleanAssert.assertTrue((boolean) result.getDecodedReturnData());}3.调试智能合约调试我们的智能合约非常容易,只需在源代码中设置断点才可!由于我们在落成调试的情况下创立了AvmRule,因此在超过断点时将暂停继续执行。

让我们来看一个例子。这是部署后智能合约的状态。【nba投注网站】。

本文来源:nba下注官网-www.mymajidwrite.com

相关文章