2

I am testing my contract via the chai and truffle-assertions libraries from a JavaScript file and am testing if events return the correct values. I have an event called Message. In my function, the event is called twice consecutively but with a different id and message. The problem I have is that it gives me an error whenever I try to test for both events even though I checked it on remix and everything seems to work. Just testing for the events (truffleAssert.eventEmitted(result, 'Message');) works fine.

I can't give the events two different names as it will create a mess for the later development of my contracts and I'll end up with an enormous amount of events.

How can I get the tests to work? Is there a workaround this error?

Similar to the below (can't share my actual code though):

event Message(address id, bytes16 message);

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

And my test file looks pretty much like this:

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

})

})

The latest error message I am getting is that I am expecting the event to return the 0x1fe... address but instead it returns the 0x0 address so it looks like it's only looking at the return of the latest event. At the same time, even if I input the 0x0 address for both events it still returns an error message.

Thanks!

3 Answers 3

3

While Aquila's answer can work as a workaround, the way truffleAssert.eventEmitted() works is by applying a filter function on the event's arguments. The drawback of this is that you can't "assert" each argument individually, but this will allow you to run both assertions in this fashion.

I saw from your other question that you're using Truffle v5 with Solidity v0.5.0, so I updated your tests to use Web3 v1.0.

I used the following solidity code to test:

event Message(address id, bytes16 message);

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

And changed the Javascript tests to:

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

Both of these tests pass with Truffle v5, Solidity v0.5.0, truffle-assertions v0.7.1.

3
  • I am getting the same problem that it's giving me the error message that "events not emitted". For now I settled on just making sure it's testing that the events exist but not what's inside the events.
    – Emul
    Dec 6, 2018 at 11:13
  • I updated the answer with the exact solidity and test code that I used. This should definitely work. If it doesn't, could you open an issue on the GitHub repo with the code you're using. Dec 6, 2018 at 13:41
  • I just tried it with your code and this does work. Even added an extra message with same id but different message and one which was identical and the test passed.
    – Emul
    Dec 7, 2018 at 13:38
2

First declaration of truffleAssert.eventEmitted handles all events, that is why you have the issue.

It means you need to assert all events in single truffleAssert.eventEmitted or you can use workaround like:

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

in case of contract:

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

3
  • I have tried this but it doesn't work every time. It works when the messages are completely different but if I have two events with different id's but same message it doesn't work.
    – Emul
    Nov 27, 2018 at 13:39
  • then you need to rebuild your assertion. keep one eventEmitted or build own event assertion based on result
    – Aquila
    Nov 27, 2018 at 13:56
  • I believe I did though rebuild the assertion. This means saying truffleAssert.eventEmitted(result, ....) right? I do this for every event and include the if statement depending on the id.
    – Emul
    Nov 27, 2018 at 14:37
0

For truffle 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
});

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.