Solidity – How to Unit Test Struct Values

blockchainsoliditytruffletruffle-contracttruffle-test

I'm new to Solidity development and I'm trying to figure out the best way to test a function which sets the values of a struct in my Truffle environment.

Firstly, is it expected that the result of the promise returns in the format below:

[ BigNumber { s: 1, e: 0, c: [ 5 ] }, 'John' ]

And if so is this the correct pattern to test the correct property has been set by the setter method (in this case name: John): assert.equal(res[1], "John");

See below for the example contract I'm attempting to test:

./contracts/Adoption.sol:

contract Adoption {

struct Dog {
    uint age;
    string name;
}

Dog[] public dogs;

function createDog(uint _age, string _name) public {
    dogs.push(Dog(_age, _name)) - 1;
}        

}

./test/Adoption.js

return Adoption.deployed()
  .then(function(instance) {
    instance.createDog(5, "John");
    return instance.dogs(0);
  })
  .then(function(res) {
    // dog age should equal 5
    assert.equal(res[0], 5);
    // dog name should equal John
    assert.equal(res[1], "John");
  });

Best Answer

Unfortunately structures were not part of the original solidity ABI specification so they will return instead a tuple of values.

Another problem is that javascript doesn't support integer with sufficient precision. To avoid problems like losing precision or rounding errors web3 will wrap integers to objects BigNumber, see What are *C*, *E* and *S* properties in message call return object? for other details.

To compare BigNumbers you can convert them to ordinary javascripts numbers with .toNumber() (this will only work for small integers https://stackoverflow.com/questions/307179/what-is-javascripts-highest-integer-value-that-a-number-can-go-to-without-losin), for large numbers probably is best to convert to string or use some of the methods from BigNumber library.

return Adoption.deployed()
  .then(function(instance) {
    instance.createDog(5, "John");
    return instance.dogs(0);
  })
  .then(function(res) {
    // dog age should equal 5
    assert.equal(res[0].toNumber(), 5);
    // dog name should equal John
    assert.equal(res[1], "John");
  });
Related Topic