Der Vertragsstatus ändert sich während Truffle-Tests nicht

Ich versuche, meine Verträge mit der Truffle-Suite zusammen mit Ganache zu testen.

Bisher habe ich Vertragsfunktionen getestet, die viewnur auf beschränkt sind. Wenn ich jetzt versuche, Änderungen am Vertragsstatus vorzunehmen, stelle ich fest, dass der Status zwischen Funktionsaufrufen nicht wirklich geändert wird.

Betrachten Sie den folgenden einfachen Vertrag:

pragma solidity ^0.4.24;

import "../OrderBook.sol";

contract IdManager {
    uint256 newId;

    function addId() public returns (uint256) {
        newId++;
        return newId;
    }
}

Alles, was ich tun möchte, ist, newIdden neuen Wert zu erhöhen und zurückzugeben.

Der Code, den ich geschrieben habe, um dies zu testen, lautet:

const { getWeb3, getContractInstance, parseSignature } = require("./test_helper");
const web3 = getWeb3();
const getInstance = getContractInstance(web3);

contract('IdManager', (accounts) => {
    let IdManager = getInstance('IdManager');

    it('test addId()', async () => {
        console.log(await IdManager.methods.addId().call());
        console.log(await IdManager.methods.addId().call());
        console.log(await IdManager.methods.addId().call());
    });
});

Der getInstance()Aufruf erfolgt Web3 v1.0anhand dieses Tutorials .

Mit dem obigen Test würde ich erwarten, dass die Ausgabe lautet:

1
2
3

Aber ich bekomme tatsächlich:

1
1
1

Ist jemand schon einmal auf dieses Problem gestoßen?


Bearbeiten0:

console.log(await IdManager.methods.newId().call()); hätte sein sollen console.log(await IdManager.methods.addId().call());newId()ist jetzt addId().


Bearbeiten1:

Auf Anraten von goodvibration habe ich den Beispielvertrag wie folgt geändert:

contract IdManager {
    uint256 public newId;

    function addId() public {
        newId++;
    }

    function getId() public view returns (uint256) {
        return newId;
    }
}

Der Testcode wurde wie folgt geändert:

it('test addId()', async () => {
    await IdManager.methods.addId().call();
    console.log(await IdManager.methods.getId().call());

    await IdManager.methods.addId().call();
    console.log(await IdManager.methods.getId().call());

    await IdManager.methods.addId().call();
    console.log(await IdManager.methods.getId().call());
});

Leider zeigt meine Ausgabe immer noch, dass der Zustand nicht beibehalten wird:

0
0
0
Sie rufen addIdin Ihrem Test nirgendwo an!!!!!
Ich habe meine Frage aktualisiert, newId()hätte sein sollen addId(). Entschuldigung.
Was ist OrderBook??? Ist das möglicherweise der alte Vertrag, mit dem Sie versucht haben, diesen Test durchzuführen?
Tut mir leid, ich habe keinen sehr guten Tag. Ich ziehe da aus den falschen Tests! Ich habe meine Frage nochmal aktualisiert.

Antworten (3)

Eine einfache Lösung dafür war direkt vor meiner Nase. Offensichtlich musste ich nur die Dokumentation lesen , die mir gegeben wurde.

Methoden.meineMethode.Aufruf

Note Calling kann den Smart-Contract-Status nicht verändern .

Methoden.meineMethode.send

Beachten Sie, dass dies den Smart-Contract-Status ändern kann .

Die Änderung an der letzten Passage des Testcodes in meiner Frage lautet also wie folgt:

it('test addId()', async () => {
    await IdManager.methods.addId().send({from: accounts[0]});
    console.log(await IdManager.methods.getId().call());

    await IdManager.methods.addId().send({from: accounts[0]});
    console.log(await IdManager.methods.getId().call());

    await IdManager.methods.addId().send({from: accounts[0]});
    console.log(await IdManager.methods.getId().call());
});

Was zu meiner gewünschten Ausgabe führt:

1
2
3

Funktion addIdist eine nicht konstante Funktion (dh nicht als pureoder deklariert view).

Daher kann sein Rückgabewert nur in der On-Chain verwendet werden, dh von anderen Funktionen (im selben Vertrag oder in anderen Verträgen), die ihn aufrufen.

Wenn Sie eine solche Funktion von der Off-Chain aufrufen, wird eine Transaktion in der On-Chain ausgeführt, und Sie erhalten im Gegenzug eine Quittung für diese Transaktion.

Wenn Sie den tatsächlichen Rückgabewert wünschen, müssen Sie emitihn in einer event, die Sie später aus der Quittung entnehmen können, angeben.

Zum Beispiel:

event Event(uint256 val);
function addId() public returns (uint256) {
    newId++;
    emit Event(newId);
    return newId;
}

Da Sie in Ihrem speziellen Fall den Wert einer globalen (Zustands-)Variablen zurückgeben, können Sie sie alternativ deklarieren publicund dann einfach mit ihrer (impliziten) Getter-Funktion aus dem Vertrag lesen:

console.log(await IdManager.methods.newId().call());
Ich hätte daran denken sollen, dass das Ausführen solcher Funktionen nur die Tx-Quittung zurückgibt, seit ich ausschließlich Web3and verwendet habe remix! Aber ich habe meinen Testcode geändert, um das Mitglied Idüber einen separaten Funktionsaufruf abzurufen. Ich sehe immer noch keine Statusänderung zwischen Anrufen.

Ab Dezember 2021 hat Truffle die Art und Weise geändert, wie Verträge aufgerufen werden sollten. Diese Frage ist extrem wichtig für jemanden, der so unaufmerksam ist wie ich, deshalb hier ein Beispieltest für den Vertrag von Edit1

const idmanager= artifacts.require("IdManager"); 

contract('IdManager', async accounts => {

    it('test addId()', async () => {
        const instance = idmanager.deployed(); 

        await instance.addId({from: account[0]}); 
        const actual = await instance.getId.call({from: account[0]});

        assert.equal(actual, 1); 
    });
});