web-dev-qa-db-fra.com

Test ethereum Event Logs à la truffe

J'ai une fonction de contrat qui émet des événements à chaque appel.

Je voudrais avoir un événement qui passe avec succès sur chaque test, voici quelques tests:

it("should emit Error event when sending 5 ether", function(done){
  var insurance = CarInsurance.deployed();

  insurance.send({from: accounts[0], value: web3.toWei(5, 'ether')}).then(done).catch(done);
});

it("should emit Error event when sending 5 ether", function(done){
  var insurance = CarInsurance.deployed();

  insurance.send({from: accounts[0], value: web3.toWei(5, 'ether')}).then(function(txHash){
    assert.notEqual(txHash, null);
  }).then(done).catch(done);
});

it("should emit Error event when sending 5 ether", function(done){
  var insurance = CarInsurance.deployed();

  insurance.send({from: accounts[0], value: web3.toWei(5, 'ether')}).then(function(done){
    done();
  }).catch(done);
});

Les résultats sont:

1) should emit Error event when sending 5 ether

Events emitted during test:
---------------------------

Error(error: Must send 10 ether)

---------------------------
✓ should emit Error event when sending 5 ether (11120ms)
✓ should emit Error event when sending 5 ether (16077ms)


3 passing (51s)
1 failing

1) Contract: CarInsurance should emit Error event when sending 5 ether:
 Error: done() invoked with non-Error: 0x87ae32b8d9f8f09dbb5d7b36267370f19d2bda90d3cf7608629cd5ec17658e9b

Vous pouvez voir que le seul qui est enregistré échoue.

Une idée ?

Je vous remercie

11
ltheron

Vous passez tx hash dans la fonction done (). Je pense que le problème est en ligne:

insurance.send({from: accounts[0], value: web3.toWei(5, 'ether')}).then(done).catch(done);

Changez le en:

insurance.send({from: accounts[0], value: web3.toWei(5, 'ether')}).then(function() { done(); }).catch(done);

Pour tester des événements:

it("should check events", function(done) {
  var watcher = contract.Reward();

  // we'll send rewards
  contract.sendReward(1, 10000, {from: accounts[0]}).then(function() {
    return watcher.get();
  }).then(function(events) {
    // now we'll check that the events are correct
    assert.equal(events.length, 1);
    assert.equal(events[0].args.beneficiary.valueOf(), 1);
    assert.equal(events[0].args.value.valueOf(), 10000);
  }).then(done).catch(done);
});
12
Aldekein

Depuis Truffle v3, vous obtenez les journaux dans le résultat du rappel. Pour que vous puissiez faire quelque chose comme:

insurance.send({from: accounts[0], value: web3.toWei(5, 'ether')}).then((result) => { assert.equal(result.logs[0].event, "Error", "Expected Error event") })

Voir https://github.com/trufflesuite/truffle-contract#processing-transaction-results

6
satolizard

Il y a un assistant pour faire ceci:

npm install --save truffle-test-utils

Au sommet de votre test:

require('truffle-test-utils').init();

Dans votre test:

let result = await insurance.send({from: accounts[0], value: web3.toWei(5, 'ether')});
assert.web3Event(result, {
  event: 'Error',
  args: {
    error: 'Must send 10 ether'
  }
}, 'Error event when sending 5 ether');

Divulgation complète: je suis l'auteur de ce paquet. Je l'ai écrit après avoir cherché une telle solution sur SO, mais je ne l'ai pas trouvée. 

5
philippe_b

Au lieu d’écrire le vôtre, vous pouvez également utiliser le test utils de Truffle expectEvent.js :

const { inLogs } = require('openzeppelin-solidity/test/helpers/expectEvent')
require('chai').use(require('chai-bignumber')(BigNumber)).should()
...
{ logs: this.logs } = await this.token.burn(amount, { from: owner })
...
const event = inLogs(this.logs, 'Burn')
event.args.burner.should.eq(owner)
event.args.value.should.be.bignumber.equal(amount)

Un exemple peut être trouvé dans BurnableToken.behavior.js de Truffle.

1
Richard Fu

Vous pouvez utiliser le package truffle-assertions, qui contient une assertion pour vérifier qu'un événement a été émis. Il a également la possibilité de passer une fonction de filtre afin de vérifier des conditions complexes pour les arguments d'événement.

npm install truffle-assertions

Vous pouvez l'importer en haut de votre fichier de test:

const truffleAssert = require('truffle-assertions');

Et utilisez-le dans votre test:

let txResult = await insurance.send({from: accounts[0], value: web3.toWei(5, 'ether')});
truffleAssert.eventEmitted(txResult, 'Error', (ev) => {
    return ev.error === 'Must send 10 ether';
}

Clause de non-responsabilité: j'ai créé ce paquet pour l'utiliser dans mes propres tests, et en ajoutant la fonction de filtrage, il est possible de vérifier des conditions complexes pour les arguments d'événement, de manière très simple. J'ai écrit un article expliquant cela plus en détail sur mon blog.

0
Rosco Kalis

J'ai été en mesure de trouver des références pour vous aider, surtout si vous souhaitez utiliser async/wait.

it('can create a unique star and get its name', async function () {
        const event = this.contract.starClaimed({});
        event.watch(async (err, result) => {
           if (err) console.log("Somethings wrong...");

           if (result.args.owner === accounts[0]) {
               let token = result.args._token;
               event.stopWatching;

               const star = await this.contract.tokenIdToStarInfo(token);

               assert.equal(star[0], 'awesome star!');
               assert.equal(star[1], 'yada yada yada');
               assert.equal(star[2], 'dec_test');
               assert.equal(star[3], 'mag_test');
               assert.equal(star[4], 'cent_test');
           }
        });

        await this.contract.createStar('awesome star!', 'yada yada yada', 'dec_test', 'mag_test', 'cent_test', {from: accounts[0]});
    });

Voici la référence que j'ai trouvée: https://github.com/trufflesuite/truffle-contract/issues/117

0
James Grunewald