Grundlegende Tests mit Truffle (ohne Änderung des Vertragsstatus)

Ich fange gerade an, Truffle zu verwenden, um diesen Vertrag zu testen

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;
    }
}

Der relevante Testcode ist

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()
      })
  })

Auf diesen Test folgt einer, um zu erhalten value. Ich hätte erwartet, 40 zurück zu bekommen, aber stattdessen bekomme ich diese Ausgabe

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


  3 passing (114ms)

Wie kann ich den neuen Wert im Test senden?

Antworten (1)

Es gibt ein paar Probleme in Ihrem Vertrag und Ihrem Test:

- Soliditätsvertrag

Sie müssen einen Aufruf (Readonly-Methode) von einer Transaktion (Schreibmethode, die den Zustand ändert) unterscheiden. Das Schlüsselwort constantwird verwendet, um die Methode als readOnly anzugeben, was bedeutet, dass keine Zustandsvariablen manipuliert werden.

Darüber hinaus ist eine Transaktion immer asynchron, da die Transaktion zuerst an das Peer2p-Netzwerk gesendet und dann von einem Miner abgebaut werden muss. Dies kann einige Zeit dauern (insbesondere in einem echten Netzwerk wie Testnet oder Mainnet).

Sie können also keinen zurückgegebenen Wert erwarten, wenn Sie die Transaktion von außen senden (Web3 und Truffle).

Der Vertrag würde so aussehen:

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;
    }
}

- Trüffeltest

Zweitens ist Ihr Test nicht korrekt, da Sie von der Transaktion keinen zurückgegebenen Wert erwarten können. Sie müssen anrufen, getValue.call()nachdem die Transaktion gesendet wurde.

Ein weiterer Gedanke, mit byte32Typ, müssen Sie sich mit Hexadezimalwerten befassen. web3.fromAsciiSie müssen also web3-Funktionen und verwenden web3.toAscii.

Letzter Punkt: Sie können direkt anrufen, Basic.deployed()um die bereitgestellte Instanz abzurufen.

Ich habe deinen Test angepasst:

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");
        });
    });


});

Und hier ist das Ergebnis:

  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

Ich habe das vollständige Projekt hier auf GitHub für weitere Details veröffentlicht.

Wahnsinn, danke für die ausführliche Antwort! Habe eine Menge gelernt.
Sehr hilfreicher Kommentar, ich hatte einige der gleichen Probleme. Ich verstehe noch nicht ganz, warum getValue.call() verwendet wird, während setValue() direkt aufgerufen wird. Dennoch funktionierte das Befolgen dieses Musters, die Funktion direkt aufzurufen, wenn ich eine Transaktion benötige, für mich wie oben.
Ich habe das gleiche Problem, aber mit Ihrer Lösung war ich nicht verfügbar, um es zu beheben. Der Test in Solidity funktioniert perfekt, aber in Javascript ändert sich die Zustandsvariable nicht. github.com/work-in-blocks/echo-blockchain