0

I'm just starting to use Truffle to test this contract

pragma solidity ^0.4.11;

contract Basic {
    bytes32 value;

    function Basic() {
        value = "mcansado";
    }

    function getValue() constant returns(bytes32) {
        return value;
    }

    function setValue(bytes32 _value) constant returns(bytes32) {
        value = _value;
    }
}

The relevant test code is

it("Should set value to 40", function(done) {
    basic.setValue(40, {from:accounts[0], to:basic.address})
    .then(function(tx) {
      console.log(tx)
      //assert.isOk(tx.receipt)
      done()
    }, function(error) {
        assert.equal(true, false)
        console.error(error)
        done()
      })
  })

That test is followed by one to get value. I would expected to get 40 back but instead I get this output

Contract: Basic
0x7d32e47118fbc082af1350062f10efee2694ff15
    ✓ Should retrive deployed contract.
0x0000000000000000000000000000000000000000000000000000000000000000
    ✓ Should set value to 40 (43ms)
mcansado // returns the value made by constructor, not 40
    ✓ Should return the value set as 40


  3 passing (114ms)

How can I send the new value in the test?

5

There are a couple of issues in your contract and your test:

- Solidity Contract

You must differentiate a call (readonly method) from a transaction (write method that change the state). The keyword constant is used to specify the method as readOnly which means that no state variables are manipulated.

Moreover, a transaction is always asynchronous because the transaction needs first to be broadcast to the peer2p network, then mined by a miner, this could take time (especially on a real network such as testnet or mainnet).

So you can't expect any value returned when you send the transaction from outside (Web3 ans Truffle).

The contract would look like that:

pragma solidity ^0.4.11;

contract Basic {
    bytes32 value;

    function Basic() {
        value = "mcansado";
    }

    function getValue() constant returns(bytes32) {
        return value;
    }

    function setValue(bytes32 _value)  {
        value = _value;
    }
}

- Truffle Test

Secondly, your test isn't correct because you can't expect a returned value from the transaction, you need to call getValue.call() after the transaction has been sent.

Another think, with byte32 type, you must deal with hexadecimal value. So you must use web3 functions web3.fromAscii and web3.toAscii.

Last point, you can directly call Basic.deployed() to get the deployed instance.

I adapted your test:

var Basic = artifacts.require("./Basic.sol");

contract('Basic', function(accounts) {

    var basic;

    it("Should set value to 40", function() {

        return Basic.deployed().then(function(instance) { // Get deployed contract
            basic = instance;

            return basic.getValue.call(); // call getValue function

        }).then(function(result) {
            console.log("#######################");
            console.log("result (hexa)=" + result); // in hexa
            console.log("result (ascii)=" + web3.toAscii(result)); // in ascii

            return basic.setValue(web3.fromAscii("40"), {from: accounts[0]}); // send transaction setValue function

        }).then(function(receipt) {
            console.log("#######################");
            console.log("transaction receipt");
            console.log(receipt);

            return basic.getValue.call(); // call getValue function

        }).then(function(result) {
            console.log("#######################");
            console.log("result (hexa)=" + result); // in hexa
            console.log("result (ascii)=" + web3.toAscii(result)); // in ascii
            assert.equal(web3.toAscii(result), "40");
        });
    });


});

And here is the result:

  Contract: Basic
#######################
result (hexa)=0x6d63616e7361646f000000000000000000000000000000000000000000000000
result (ascii)=mcansado
#######################
transaction receipt
{ tx: '0x051654a9fc0aaeb44ff54229c31ab91e9ad9fe9b03da4498d978740e760d739c',
  receipt:
   { transactionHash: '0x051654a9fc0aaeb44ff54229c31ab91e9ad9fe9b03da4498d978740e760d739c',
     transactionIndex: 0,
     blockHash: '0x106da8c6862f2caf94d40cf866d4b9a61b9c7839d7608fab00e114700dc3eb93',
     blockNumber: 108,
     gasUsed: 26695,
     cumulativeGasUsed: 26695,
     contractAddress: null,
     logs: [] },
  logs: [] }
#######################
result (hexa)=0x3430000000000000000000000000000000000000000000000000000000000000
result (ascii)=40

I published the full project on GitHub here for more details.

  • This is insane, thanks for the detailed response! Learned a ton. – mcansado Aug 22 '17 at 11:33
  • Very helpful comment, I was facing some of the same issues. I'm not quite yet following why getValue.call() is used whereas setValue() is called directly. Still, following this pattern of calling the function directly when I need a transaction worked for me as it does above. – greghmerrill Sep 30 '17 at 0:13
  • Having the same problem, but with your solution i haven't been available to fix it. The test in Solidity work perfect, but in javascript the state variable won't change. github.com/work-in-blocks/echo-blockchain – alacret Aug 1 '18 at 3:49
  • ethereum.stackexchange.com/questions/55583/… @gregmerril – alacret Aug 1 '18 at 5:04

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.