Я работал с примером контракта на голосование и проводил его модульное тестирование с помощью Truffle и Javascript. До сих пор мне удалось успешно протестировать каждую функцию из моего контракта. Но когда я попытался получить свойство списка кандидатов, это не сработало. Часть тестового файла
...
it('returns every candidate', async () => {
let fundRaise = await Voting.new(['Alice', 'Bob', 'Rick']);
const cands = await voting.candidateList();
Console.log(cands);
});
...
Когда я выполняю вышеуказанный тест, трюфель показывает следующее
1) Contract: Voting returns every candidate:
Error: Invalid number of arguments to Solidity function
at Object.InvalidNumberOfSolidityArgs (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/errors.js:25:1)
at SolidityFunction.validateArgs (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:74:1)
at SolidityFunction.toPayload (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:90:1)
at SolidityFunction.call (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:131:1)
at SolidityFunction.execute (/usr/lib/node_modules/truffle/build/webpack:/~/web3/lib/web3/function.js:260:1)
at /usr/lib/node_modules/truffle/build/webpack:/~/truffle-contract/contract.js:135:1
at new Promise (<anonymous>)
at /usr/lib/node_modules/truffle/build/webpack:/~/truffle-contract/contract.js:126:1
at <anonymous>
at process._tickDomainCallback (internal/process/next_tick.js:228:7)
Чего я не понимаю, так это почему, если функция получения генерируется автоматически, web3 выдает это сообщение. У меня Truffle v4.1.7 (ядро: 4.1.7); Solidity v0.4.23 (solc-js); Geth/v1.8.1-stable-1e67410e/linux-amd64/go1.9.4"; api версии web3: '0.20.6',
Ниже приведен файл контракта, а также файл тестирования.
pragma solidity ^0.4.17;
contract Voting {
mapping (bytes32 => uint8) public votesReceived;
bytes32[] public candidateList;
constructor(bytes32[] _candidates) public {
candidateList = _candidates;
}
function voteForCandidate(bytes32 _name) public returns (uint8) {
require(validateCandidate(_name));
votesReceived[_name] += 1;
//return votesReceived[_name];
return totalVotesFor(_name);
}
function validateCandidate(bytes32 _name) view public returns (bool){
for (uint8 i = 0; i < candidateList.length; i++) {
if(candidateList[i] == _name){
return true;
}
}
return false;
}
function totalVotesFor(bytes32 name) view public returns (uint8){
require(validateCandidate(name));
return votesReceived[name];
}
function addCandidate(bytes32 _name) public returns (bool) {
candidateList.push(_name);
return validateCandidate(_name);
}
const assert = require('assert');
var Voting = artifacts.require("Voting");
Это тестовый файл:
contract('Voting', function(accounts) {
let voting;
beforeEach(async () => {
voting = await Voting.deployed();
});
it('votes for valid candidate', async () => {
const voto = await voting.voteForCandidate.call('Andrea');
assert.equal(voto.toNumber(),1, 'Cannot vote for valid candidate');
});
it('Does not vote for invalid candidate', async () => {
const voto = await voting.voteForCandidate.call('Bacilio');
assert.equal(voto.toNumber(), 0, 'Allowed to vote for invalid candidate');
});
it('Adds new candidate', async () => {
const voto = await voting.addCandidate.call('Segismundo');
assert.equal(voto, true, 'Did not allow to add new candidate');
});
it('allows to obtain votes casted for a candidate', async () => {
const expected_votes = 2;
//vote twice for the same candidate
await voting.voteForCandidate('Roberto');
await voting.voteForCandidate('Roberto');
let casted_votes = await voting.totalVotesFor.call('Roberto');
assert.equal(casted_votes.toNumber(), expected_votes, 'Did not got casted votes')
});
it('returns every candidate', async () => {
let fundRaise = await Voting.new(['Segismundo', 'Ocatvia']);
const cands = await voting.candidateList();
Console.log(cands);
});
});
В свой код Solidity добавьте:
function candidateListLength() external view returns (uint) {
return candidateList.length;
}
В коде Javascript добавьте:
let cands = [];
let length = Number(await voting.candidateListLength());
for (let i = 0; i < length; i++)
cands.push(await voting.candidateList(i));
Роберто С.