Solidity

測試智能合約時的問題

  • May 12, 2021

我正在使用solidity進行智能合約開發,我編寫了下面的智能合約,我對第一個函式addCandidate()的Chai和Mocha測試有一些問題

//SPDX-License-Identifier: GPL-3.0

pragma solidity >=0.5.0 <0.9.0;

contract VotingContract{
   address public moderator;
   
   struct Candidate {
       uint256 id;
       string  name;
       uint256 voteCount;
   }
   
   struct Voter {
       string name;
       mapping(address => bool)  hasVoted;
   }
   
   mapping(address => Voter) public votes;
   mapping(uint256 => Candidate) public candidateLookup; //candidates will be identified with an unique ID
   uint256 public candidateCount; //Will be used to track the number of candidates
   
   enum State {beforeStart, running, halted} 
   State public electionState;
   
   event AddedCandidate(string _name);
   event Voted( uint256 id, string _name);

   
   constructor () {
       moderator = msg.sender;
       electionState = State.beforeStart;
       candidateCount = 0; //Not really necesary to initalize to zero as per solidity documentation -> A variable which is declared will have an initial default value whose byte-representation is all zeros. The “default values” of variables are the typical “zero-state” of whatever the type is. For example, the default value for a bool is false. The default value for the uint or int types is 0
   }
   
   
   modifier onlyModerator{
       require(msg.sender == moderator, 'Only the moderator of the election can use this function');
       _;
   }
   
   modifier votingInProcess {
       require(electionState == State.running, 'The election is not active at this moment');
       _;
   }
   
   
   function addCandidate(string memory _name) public onlyModerator returns(bool){
       Candidate storage newCandidate = candidateLookup[candidateCount];
       newCandidate.id = candidateCount;
       newCandidate.name = _name;
       newCandidate.voteCount = 0;
       candidateCount++;
       emit AddedCandidate(_name);
       return true;
   }
   
   function getCandidate(uint256 _id) public view returns(uint256, string memory){
      string memory name = candidateLookup[_id].name;
      uint256 voteCount = candidateLookup[_id].voteCount;
      return (voteCount, name);
   }
   
   function getCandidates() external view returns(string[] memory, uint256[] memory){
       string [] memory names = new string[](candidateCount);
       uint256[] memory voteCounts = new uint[](candidateCount);
       for (uint256 i = 0; i < candidateCount; i++) {
           names[i] = candidateLookup[i].name;
           voteCounts[i] = candidateLookup[i].voteCount;
       }
       return (names, voteCounts);

   }
   
   
   function startVoting() external onlyModerator {
       electionState = State.running;
   }
   
   function haltVoting() external onlyModerator {
       electionState = State.halted;
   }
   
   function vote(uint256 _id, string memory _name) public votingInProcess returns (bool){
       Voter storage newVoter = votes[msg.sender];
       require(_id >= 0 && _id <= candidateCount, 'There is no candidate with the specified ID');
       require(newVoter.hasVoted[msg.sender] == false, 'You can only vote one time!');
       candidateLookup[_id].voteCount++;
       newVoter.name = _name;
       newVoter.hasVoted[msg.sender] = true;
       emit Voted(_id, _name);
       return true;
   }
}

這是我到目前為止所做的測試


//getting the contract json representation
const VotingContract = artifacts.require('./VotingContract');
const BN = web3.utils.BN;

let instance;
let accounts;
let owner;

contract('VotingContract', async(accs) => {
   accounts = accs;
   moderator = accounts[0];
})


it('Can add a candidate', async() => {
   let instance = await VotingContract.deployed();
   let id = 0;
   let newCandidateName = 'Candidate1'
   await instance.addCandidate(newCandidateName, {from: moderator});
   let request = await instance.candidateLookup.call(id)
   assert.equal(request, newCandidateName)
});

但它失敗了,這就是我收到的

 1) Can add a candidate

 0 passing (489ms)
 1 failing

 1) Can add a candidate:
    AssertionError: expected { Object (0, 1, ...) } to equal 'Candidate1'
     at Context.<anonymous> (test\VotingContract.test.js:21:12)
     at processTicksAndRejections (internal/process/task_queues.js:93:5)

我不明白 { Object (0, 1, …) } 來自哪裡,

任何人都可以指出我正確的方向嗎?這是什麼?我應該閱讀哪些文件?任何關於我開發的智能合約的額外回饋將不勝感激!

candidateLookup是一個 uint 到候選(結構)而不是字元串(candidateName)的映射。所以訪問candidateLookup總是會返回一個結構。

你可以試試

assert.equal(request[1], newCandidateName)

因為根據您的結構定義;

request[0]: id,
request[1]: name,
request[2]: voteCount

引用自:https://ethereum.stackexchange.com/questions/98798