Truffle тестирует события через JavaScript

Я тестирую свой контракт через библиотеки chai и truffle-assertions из файла JavaScript и проверяю, возвращают ли события правильные значения. У меня есть событие под названием Message. В моей функции событие вызывается дважды подряд, но с другим идентификатором и сообщением. У меня проблема в том, что она выдает ошибку всякий раз, когда я пытаюсь протестировать оба события, хотя я проверил это на ремиксе, и все, кажется, работает. Простое тестирование событий (truffleAssert.eventEmitted(result, 'Message');) работает нормально.

Я не могу давать событиям два разных имени, так как это создаст беспорядок для дальнейшей разработки моих контрактов, и в итоге я получу огромное количество событий.

Как заставить тесты работать? Есть ли обходной путь этой ошибки?

Подобно приведенному ниже (хотя я не могу поделиться своим фактическим кодом):

event Message(address id, bytes16 message);

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

И мой тестовый файл выглядит примерно так:

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.');

})

})

Последнее сообщение об ошибке, которое я получаю, заключается в том, что я ожидаю, что событие вернет адрес 0x1fe..., но вместо этого оно возвращает адрес 0x0, поэтому похоже, что оно смотрит только на возвращение последнего события. В то же время, даже если я ввожу адрес 0x0 для обоих событий, он все равно возвращает сообщение об ошибке.

Спасибо!

Ответы (3)

Хотя ответ Aquila может работать как обходной путь, truffleAssert.eventEmitted()он работает, применяя функцию фильтра к аргументам события. Недостатком этого является то, что вы не можете «утвердить» каждый аргумент по отдельности, но это позволит вам запускать оба утверждения таким образом.

Из вашего другого вопроса я понял, что вы используете Truffle v5 с Solidity v0.5.0, поэтому я обновил ваши тесты, чтобы использовать Web3 v1.0.

Я использовал следующий код прочности для тестирования:

event Message(address id, bytes16 message);

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

И изменил тесты Javascript на:

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.');
  })

Оба этих теста проходят с Truffle v5, Solidity v0.5.0, truffle-assertions v0.7.1.

Я получаю ту же проблему, что и сообщение об ошибке, что «события не испускаются». На данный момент я решил просто убедиться, что это проверка того, что события существуют, но не то, что находится внутри событий.
Я обновил ответ, указав точную надежность и тестовый код, который я использовал. Это определенно должно сработать. Если это не так, не могли бы вы открыть проблему в репозитории GitHub с кодом, который вы используете.
Я только что попробовал это с вашим кодом, и это действительно работает. Даже добавлено дополнительное сообщение с тем же идентификатором, но другим сообщением, которое было идентичным, и тест прошел.

Первое объявление truffleAssert.eventEmittedобрабатывает все события, поэтому у вас возникла проблема.

Это означает, что вам нужно утверждать все события в одном truffleAssert.eventEmittedили вы можете использовать обходной путь, например:

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.');
})

в случае контракта:

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/трюфель-утверждения

Я пробовал это, но это не работает каждый раз. Это работает, когда сообщения совершенно разные, но если у меня есть два события с разными идентификаторами, но с одним и тем же сообщением, это не работает.
тогда вам нужно перестроить свое утверждение. сохранить одно eventEmittedили создать собственное утверждение события на основеresult
Я считаю, что я сделал, хотя восстановить утверждение. Это означает говорить truffleAssert.eventEmitted(result, ....), верно? Я делаю это для каждого события и включаю оператор if в зависимости от идентификатора.

Для трюфеля 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
});