1

This is not a duplicate question. The other one doesn't answer the problem in any way. Can anyone explain to me why do I get No Events where emmited when running truffle test? Ganache is listening in 7545 and my truffle config file points to that port. I can see more blocks being produced in Ganache each time I run truffle test.

I am starting to think it has nothing to do with the contract code or the truffle test, but here they are:

Contract code

function addExam(string memory hash) public returns (string memory examProfessorHash) {
    // save the exam hash and link it with the professors address
    professorsExam[msg.sender] = hash;

    return professorsExam[msg.sender];
}

Test code

it("should add an exam to the exams list", async () => {
    let hash_test = "9F86D081884C7D659A2FEAA0C55AD015A3BF4F1B2B0B822CD15D6C15B0F00A08";
    let instance = await Exam.deployed();
    let hash = await instance.addExam(hash_test, {from: accounts[0]});
    assert.equal(hash.valueOf(), hash_test, "Not returning the correct address");

Why do I get

Contract: Exams ✓ should pass this test

No events were emitted

1) should add an exam to the exams list

No events were emitted

  • 1
    Can you at least link to the question that you find insufficient? Thanks – Ann Kilzer Nov 28 '19 at 3:04
  • Side note: you're suffering misconception of how things work. When you call a non-constant (neither pure nor view) function from the off-chain (i.e., from a web3 script and not from another contract), you do not get back the value that this function returns, because it is not known whether the transaction has been mined. Instead, you get a transaction-hash (don't confuse this with the fact that yur return-value happens to be named "hash", probably due to your internal logic). – goodvibration Nov 28 '19 at 7:33
  • In order to obtain the actual return-value, you need to: 1. In the contract - emit an event containing the return-value, before returning it. 2. In the script - obtain the receipt associated with that transaction-hash, and extract the event from it. You may get the receipt directly (i.e., instead of taking the transaction hash and request the corresponding receipt from the node), if you await for the transaction to complete (as you do in your case). So all you really have left to do is something like emit MyEvent(professorsExam[msg.sender]) before return professorsExam[msg.sender]. – goodvibration Nov 28 '19 at 7:36
0

Your addExam function is not a view or pure function and it modifies the state of the contract. Therefore it returns a transaction hash and not the real function return value because the transaction needs to be mined before it can give you the result.

Your test fails because you assert that the return value is the desired address when the return value is only the transaction hash. And when a truffle test fails it shows you the events which were emitted during the execution - in your case you are not emitting any events and therefore it just says that no events were emitted. You can read a bit more detauls here: How to fix "No events were emitted"

| improve this answer | |
0

Following my comments to your question (please read through), here is how you can fix your code:

In the contract:

event ExamAdded(string hash);

function addExam(string memory hash) public returns (string memory examProfessorHash) {
    // save the exam hash and link it with the professors address
    professorsExam[msg.sender] = hash;
    emit ExamAdded(professorsExam[msg.sender]);
    return professorsExam[msg.sender];
}

In the test:

it("should add an exam to the exams list", async () => {
    const hash_test = "9F86D081884C7D659A2FEAA0C55AD015A3BF4F1B2B0B822CD15D6C15B0F00A08";
    const instance = await Exam.deployed();
    const response = await instance.addExam(hash_test, {from: accounts[0]});
    assert.equal(response.logs[0].args.hash, hash_test, "Not returning the correct address");
});

Note that:

  • emit ExamAdded(professorsExam[msg.sender]); is useful only when the function is called from the off-chain (i.e., from a web3 script)
  • return professorsExam[msg.sender]; is useful only when the function is called from the on-chain (i.e., from this contract or from another contract)

Therefore, you should generally add each one of these statements only if they are really needed.

Side note: for your purpose, it seems that you can use bytes32 instead of string, which would make your code more efficient (less gas-consuming).

| improve this answer | |
  • This is changing the testing logic, not testing for the actual return value. But maybe that's ok for the OP, unsure. – Lauri Peltonen Nov 28 '19 at 7:54
  • @LauriPeltonen: Well, that's true I suppose, though since the emit statement and the return statement are identical in contents, it kinda keeps the logic I believe. – goodvibration Nov 28 '19 at 8:08

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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