Truffle Tests Events über JavaScript

Ich teste meinen Vertrag über die Bibliotheken chai und truffle-assertions aus einer JavaScript-Datei und teste, ob Ereignisse die richtigen Werte zurückgeben. Ich habe ein Ereignis namens Nachricht. In meiner Funktion wird das Ereignis zweimal hintereinander aufgerufen, jedoch mit einer anderen ID und Nachricht. Das Problem, das ich habe, ist, dass es mir einen Fehler gibt, wenn ich versuche, auf beide Ereignisse zu testen, obwohl ich es auf Remix überprüft habe und alles zu funktionieren scheint. Nur das Testen der Ereignisse (truffleAssert.eventEmitted(result, 'Message');) funktioniert einwandfrei.

Ich kann den Ereignissen nicht zwei verschiedene Namen geben, da dies die spätere Entwicklung meiner Verträge durcheinander bringen würde und ich am Ende eine enorme Menge an Ereignissen haben würde.

Wie kann ich die Tests zum Laufen bringen? Gibt es eine Problemumgehung für diesen Fehler?

Ähnlich wie unten (kann meinen tatsächlichen Code jedoch nicht teilen):

event Message(address id, bytes16 message);

function messages() public {
emit Message(0x1fe..., 'Almost there);
emit Message(0x0, 'Congratulations'); 
}

Und meine Testdatei sieht ungefähr so ​​​​aus:

const Contract = artifacts.require('./Contract.sol')
const assert = require("chai").assert;
const truffleAssert = require('truffle-assertions');

contract('Contract', function(accounts) {
  let contractInst;
  let owner = accounts[0];
  let user1 = accounts[1];
  let user2 = accounts[2];

  before('getting instance before all Test Cases', async function(){
    contractInst = await Contract.new({from: owner});

  })

it("should check that the correct events are returned", async () => {
  let result = await contractInst.messages();

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
      assert.equal(ev.id, user1, 'Correct id was returned');
      assert.equal(web3.toUtf8(ev.message), "Almost there", 'Correct message was returned.');
      return true;
    }, 'Contract should return the correct message.');

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
      assert.equal(ev.id, user2, 'Correct id was returned');
      assert.equal(web3.toUtf8(ev.message), "Congratulations", 'Correct message was returned.');
      return true;
    }, 'Contract should return the correct message.');

})

})

Die letzte Fehlermeldung, die ich erhalte, ist, dass ich erwarte, dass das Ereignis die Adresse 0x1fe ... zurückgibt, aber stattdessen die Adresse 0x0 zurückgibt, sodass es so aussieht, als würde es nur die Rückgabe des letzten Ereignisses betrachten. Gleichzeitig gibt es immer noch eine Fehlermeldung zurück, selbst wenn ich die 0x0-Adresse für beide Ereignisse eingebe.

Danke!

Antworten (3)

Während die Antwort von Aquila als Problemumgehung funktionieren kann, truffleAssert.eventEmitted()funktioniert dies, indem eine Filterfunktion auf die Argumente des Ereignisses angewendet wird. Der Nachteil dabei ist, dass Sie nicht jedes Argument einzeln "behaupten" können, aber dies ermöglicht es Ihnen, beide Behauptungen auf diese Weise auszuführen.

Ich habe aus Ihrer anderen Frage gesehen, dass Sie Truffle v5 mit Solidity v0.5.0 verwenden, also habe ich Ihre Tests aktualisiert, um Web3 v1.0 zu verwenden.

Ich habe den folgenden Solidity-Code zum Testen verwendet:

event Message(address id, bytes16 message);

function messages() public {
    emit Message(address(0), "Almost there");
    emit Message(address(msg.sender), "Congratulations");
}

Und die Javascript-Tests geändert in:

it("should check that the correct events are returned", async () => {
    let result = await casino.messages();

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
      return ev.id === '0x0000000000000000000000000000000000000000' && web3.utils.hexToUtf8(ev.message) === 'Almost there';
    }, 'Contract should return the correct message.');

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
      return ev.id === accounts[0] && web3.utils.hexToUtf8(ev.message) === 'Congratulations';
    }, 'Contract should return the correct message.');
  })

Beide Tests bestehen mit Truffle v5, Solidity v0.5.0, truffle-assertions v0.7.1.

Ich bekomme das gleiche Problem, dass es mir die Fehlermeldung gibt, dass "Ereignisse nicht ausgegeben werden". Im Moment habe ich mich darauf festgelegt, nur sicherzustellen, dass es testet, ob die Ereignisse existieren, aber nicht, was in den Ereignissen enthalten ist.
Ich habe die Antwort mit dem genauen Soliditäts- und Testcode aktualisiert, den ich verwendet habe. Das sollte auf jeden Fall funktionieren. Wenn dies nicht der Fall ist, könnten Sie mit dem von Ihnen verwendeten Code ein Problem im GitHub-Repo öffnen.
Ich habe es gerade mit deinem Code versucht und das funktioniert. Es wurde sogar eine zusätzliche Nachricht mit derselben ID, aber einer anderen Nachricht hinzugefügt, und eine, die identisch war, und der Test wurde bestanden.

Die erste Deklaration von truffleAssert.eventEmittedbehandelt alle Ereignisse, deshalb haben Sie das Problem.

Dies bedeutet, dass Sie alle Ereignisse einzeln geltend machen müssen, truffleAssert.eventEmittedoder Sie können eine Problemumgehung wie folgt verwenden:

it("should check that the correct events are returned", async () => {
    let result = await contractInst.messages({from: user1});

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
        if(ev.id !== user1) return;                               // <- exit in case of second event
        assert.equal(ev.id, user1, 'Correct id was returned');
        assert.equal(web3.toUtf8(ev.message), "Almost there", 'Correct message was returned.');
        return true;
    }, 'Contract should return the correct message.');

    truffleAssert.eventEmitted(result, 'Message', (ev) => {
        if(ev.id === user1) return;                               // <- exit in case of first event
        assert.equal(ev.id, '0x0000000000000000000000000000000000000000', 'Correct id was returned');
        assert.equal(web3.toUtf8(ev.message), "Congratulations", 'Correct message was returned.');
        return true;
    }, 'Contract should return the correct message.');
})

im Vertragsfall:

pragma solidity ^0.4.21;

contract Ev {
    event Message(address id, bytes16 message);

    function messages() public {
        emit Message(msg.sender, 'Almost there');
        emit Message(0x0, 'Congratulations'); 
    }
}

https://github.com/rkalis/truffle-assertions

Ich habe das versucht, aber es funktioniert nicht jedes Mal. Es funktioniert, wenn die Nachrichten völlig unterschiedlich sind, aber wenn ich zwei Ereignisse mit unterschiedlichen IDs, aber derselben Nachricht habe, funktioniert es nicht.
Dann müssen Sie Ihre Behauptung neu aufbauen. Behalte eine eventEmittedoder erstelle eine eigene Event-Assertion basierend aufresult
Ich glaube, ich habe die Behauptung zwar umgebaut. Das bedeutet, truffleAssert.eventEmitted(result, ....) richtig zu sagen? Ich mache das für jedes Ereignis und füge die if-Anweisung abhängig von der ID hinzu.

Für Trüffel v5

it("...",async ()=>{
    const result = await contractInst.messages({from: user1});
    const events = await contractInst.getPastEvents('Message');
    // iterate over the events
    // and do the necessary assertions
});