Ich versuche, meine Verträge mit der Truffle-Suite zusammen mit Ganache zu testen.
Bisher habe ich Vertragsfunktionen getestet, die view
nur 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, newId
den 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.0
anhand 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
Eine einfache Lösung dafür war direkt vor meiner Nase. Offensichtlich musste ich nur die Dokumentation lesen , die mir gegeben wurde.
Note Calling kann den Smart-Contract-Status nicht verändern .
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 addId
ist eine nicht konstante Funktion (dh nicht als pure
oder 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 emit
ihn 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 public
und dann einfach mit ihrer (impliziten) Getter-Funktion aus dem Vertrag lesen:
console.log(await IdManager.methods.newId().call());
Web3
and 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);
});
});
gute Stimmung
addId
in Ihrem Test nirgendwo an!!!!!Craig
newId()
hätte sein sollenaddId()
. Entschuldigung.gute Stimmung
OrderBook
??? Ist das möglicherweise der alte Vertrag, mit dem Sie versucht haben, diesen Test durchzuführen?Craig