2

I just starting out looking at Ethereum and am trying to test a Contract (using the simple cryptocurrency contract as an example) using Mocha, so I can take advantage of things like chai and sinon, etc, and stick to the rspec like format they follow.

The contract looks like:

contract MetaCoin {
  mapping (address => uint) balances;

  function MetaCoin() {
    balances[tx.origin] = 10000;
  }

  function sendCoin(address receiver, uint amount) returns(bool sufficient) {
    if (balances[msg.sender] < amount) return false;

    balances[msg.sender] -= amount;
    balances[receiver] += amount;
    return true;
  }

  function getBalanceInEth(address addr) constant returns(uint) {
    return getBalance(addr) * 2;
  }

  function getBalance(address addr) constant returns(uint) {
    return balances[addr];
  }
}

The test looks like:

import {expect}   from 'chai';
import fs         from 'fs';
import solc       from 'solc';
import Pudding    from 'ether-pudding';
import TestRPC    from 'ethereumjs-testrpc';
import Web3       from 'web3';

const name = 'MetaCoin';

describe(name, () => {
  let ContractJS, address;

  before((done) => {

    const result = solc.compile(fs.readFileSync(`./contracts/${name}.sol`,
                                {encoding: "utf8"}), 1);
    const compiled = result.contracts[name];
    const abi = JSON.parse(compiled.interface);
    const binary = compiled.bytecode;
    const web3 = new Web3();
    const provider = TestRPC.provider({
      accounts: [{
        balance: 50000000
      }]
    });
    web3.setProvider(provider);

    web3.eth.getAccounts((err, accounts) => {
      address = accounts[0];
      ContractJS = Pudding.whisk(name, {
        abi: abi,
        binary: binary,
        address: address
      });
      ContractJS.setProvider(provider);
      done(err);
    });
  });

  it('has a contract instance', () => {
    expect(ContractJS).to.be.defined;
  })

  describe('#getBalance', () => {
    let instance;

    before(() => {  // put done back in if you switch this over.
      instance = ContractJS.at(address);
    });

    // This fails. balance.valueOf() is '0'
    it('gets the correct balance', (done) => {
      instance.getBalance.call(address).then((balance) => {
        expect(balance.valueOf()).to.equal('10000');
        done();
      }, done);
    });
  });
});

This test fails: complaining that '0' is not equal to '1000'.

This implies that the contract's constructor is not being invoked, or that the contract's tx.origin is a different address that the one provided. Maybe I am just missing something core and simple.

  • 1
    Try adding "constant" to the function signature of getBalance(). – Edmund Edgar Jul 14 '16 at 5:21
  • Okay thanks, I tried that to no avail. Also corrected a minor bug in the outer before clause. Alas still not working. – Dave Sag Jul 14 '16 at 5:33
  • 1
    more likely that the format or content of tx.origin and address are not the same. maybe track it with an event... – Roland Kofler Jul 14 '16 at 6:43
  • There is some nonsense here: instance = ContractJS.at(address); you are trying to instantiate contract at the address of user account. That is why calls are returning 0. You need to do something like instance = ContractJS.at(contractAddress);. Also, you might want to try github.com/ConsenSys/truffle instead of pure pudding/mocha. Your tests will become much cleaner and easier to write. – Oleksii Matiiasevych Jul 15 '16 at 8:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.