2017-07-01 1 views
0

Je développe un contrat Ethereum en utilisant Truffle et TestRPC. Mais je suis incapable d'obtenir une variable d'état pour mettre à jour. Je pense que c'est peut-être juste que j'y accède trop tôt, mais d'autres exemples de tests semblent très bien fonctionner et sont très similaires.Impossible de changer une variable d'état dans un contrat

j'ai réduit mon contrat jusqu'à la chose la plus simple possible qui casse:

pragma solidity ^0.4.11; 

contract Adder { 

    uint public total; 

    function add(uint amount) { 
     total += amount; 
    } 

    function getTotal() returns(uint){ 
     return total; 
    } 
} 

Et ceci est mon test:

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

contract('Adder', accounts => { 
    it("should start with 0",() => 
    Adder.deployed() 
     .then(instance => instance.getTotal.call()) 
     .then(total => assert.equal(total.toNumber(), 0)) 
); 

    it("should increase the total as amounts are added",() => 
    Adder.deployed() 
     .then(instance => instance.add.call(10) 
     .then(() => instance.getTotal.call()) 
     .then(total => assert.equal(total.toNumber(), 10)) 
    ) 
); 

}); 

Le premier test passe bien. Mais le deuxième test échoue parce que getTotal renvoie encore 0.

Répondre

4

Je crois que le problème est que vous utilisez toujours la méthode .call().

Cette méthode exécutera en fait le code mais ne sauvegardera pas dans la blockchain.

Vous devez utiliser la méthode .call(), uniquement lorsque vous lisez depuis la blockchain ou que vous effectuez un test pour throws.

Il suffit de supprimer le .call() dans la fonction d'ajout et cela devrait fonctionner.

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

contract('Adder', accounts => { 
    it("should start with 0",() => 
    Adder.deployed() 
     .then(instance => instance.getTotal.call()) 
     .then(total => assert.equal(total.toNumber(), 0)) 
); 

    it("should increase the total as amounts are added",() => 
    Adder.deployed() 
     .then(instance => instance.add(10) 
     .then(() => instance.getTotal.call()) 
     .then(total => assert.equal(total.toNumber(), 10)) 
    ) 
); 
}); 

En outre, envisager de déclarer la variable instance en dehors de la chaîne de fonctions de la promesse que le contexte n'est pas partagée. Pensez à utiliser async/await pour les tests au lieu des promesses.

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

contract('Adder', accounts => { 
    it("should start with 0", async() => { 
    let instance = await Adder.deployed(); 
    assert.equal((await instance.getTotal.call()).toNumber(), 0); 
    }); 

    it("should increase the total as amounts are added", async() => { 
    let instance = await Adder.deployed(); 
    await instance.add(10); 
    assert.equal((await instance.getTotal.call()).toNumber(), 10); 
    }); 
}); 
+0

Je savais que ce serait quelque chose de simple! –

+0

Et merci pour les conseils. –