Unit Testing in Truffle

I keep getting this problem, anyone an idea? @filip

truffle(ganache)> test
Using network ‘ganache’.

Compiling your contracts…

Compiling .\contracts\Ownable.sol

Contract: People
1) should’t create a person with age over 150 years
> No events were emitted

0 passing (184ms)
1 failing

  1. Contract: People
    should’t create a person with age over 150 years :
    TypeError: Cannot read property ‘REVERT’ of undefined
    at Context. (test\PeopleTest.js:7:136)
    at process._tickCallback (internal/process/next_tick.js:68:7)

1
truffle(ganache)> { Error: Returned error: VM Exception while processing transaction: revert Age needs to be below 150 – Reason given: Age needs to be below 150. at PromiEvent (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\promievent.js:6:1)
at TruffleContract.createPerson (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\execute.js:158:1)
at Context. (C:\DOC\eth\PeopleProject\test\PeopleTest.js:7:40)
at process._tickCallback (internal/process/next_tick.js:68:7)
reason: ‘Age needs to be below 150’,
hijackedStack:
‘Error: Returned error: VM Exception while processing transaction: revert Age needs to be below 150 – Reason given: Age needs to be below 150.\n at Object.ErrorResponse (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-core-helpers\src\errors.js:29:1)\n at C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-core-requestmanager\src\index.js:140:1\n at C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\provider\wrapper.js:112:1\n at XMLHttpRequest.request.onreadystatechange (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-providers-http\src\index.js:96:1)\n at XMLHttpRequestEventTarget.dispatchEvent (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request-event-target.js:34:1)\n at XMLHttpRequest._setReadyState (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request.js:208:1)\n at XMLHttpRequest._onHttpResponseEnd (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request.js:318:1)\n at IncomingMessage. (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request.js:289:47)\n at IncomingMessage.emit (events.js:203:15)\n at IncomingMessage.EventEmitter.emit (domain.js:466:23)\n at endReadableNT (_stream_readable.js:1143:12)\n at process._tickCallback (internal/process/next_tick.js:63:19)’ }
{ Error: Returned error: VM Exception while processing transaction: revert Age needs to be below 150 – Reason given: Age needs to be below 150. at PromiEvent (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\promievent.js:6:1)
at TruffleContract.createPerson (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\contract\lib\execute.js:158:1)
at Context. (C:\DOC\eth\PeopleProject\test\PeopleTest.js:7:40)
at process._tickCallback (internal/process/next_tick.js:68:7)
reason: ‘Age needs to be below 150’,
hijackedStack:
‘Error: Returned error: VM Exception while processing transaction: revert Age needs to be below 150 – Reason given: Age needs to be below 150.\n at Object.ErrorResponse (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-core-helpers\src\errors.js:29:1)\n at C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-core-requestmanager\src\index.js:140:1\n at C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\provider\wrapper.js:112:1\n at XMLHttpRequest.request.onreadystatechange (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-providers-http\src\index.js:96:1)\n at XMLHttpRequestEventTarget.dispatchEvent (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request-event-target.js:34:1)\n at XMLHttpRequest._setReadyState (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request.js:208:1)\n at XMLHttpRequest._onHttpResponseEnd (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request.js:318:1)\n at IncomingMessage. (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request.js:289:47)\n at IncomingMessage.emit (events.js:203:15)\n at IncomingMessage.EventEmitter.emit (domain.js:466:23)\n at endReadableNT (_stream_readable.js:1143:12)\n at process._tickCallback (internal/process/next_tick.js:63:19)’ }

C:\Users\VAIO-PC.config\truffle\compilers\node_modules\soljson-v0.5.12+commit.7709ece9.js:33
(Module.asmGlobalArg,Module.asmLibraryArg,buffer);var __GLOBAL__I_000101=Module["__GLOBAL__I_000101"]=asm["__GLOBAL__I_000101"];var __GLOBAL__sub_I_ABIFunctions_cpp=Module["__GLOBAL__sub_I_ABIFunctions_cpp"]=asm["__GLOBAL__sub_I_ABIFunctions_cpp"];var __GLOBAL__sub_I_ABI_cpp=Module["__GLOBAL__sub_I_ABI_cpp"]=asm["__GLOBAL__sub_I_ABI_cpp"];var __GLOBAL__sub_I_ASTJsonConverter_cpp=Module["__GLOBAL__sub_I_ASTJsonConverter_cpp"]=asm["__GLOBAL__sub_I_ASTJsonConverter_cpp"];var __GLOBAL__sub_I_AST_cpp=Module["__GLOBAL__sub_I_AST_cpp"]=asm["__GLOBAL__sub_I_AST_cpp"];var __GLOBAL__sub_I_ArrayUtils_cpp=Module["__GLOBAL__sub_I_ArrayUtils_cpp"]=asm["__GLOBAL__sub_I_ArrayUtils_cpp"];var __GLOBAL__sub_I_AsmAnalysis_cpp=Module["__GLOBAL__sub_I_AsmAnalysis_cpp"]=asm["__GLOBAL__sub_I_AsmAnalysis_cpp"];var __GLOBAL__sub_I_BMC_cpp=Module["__GLOBAL__sub_I_BMC_cpp"]=asm["__GLOBAL__sub_I_BMC_cpp"];var GLOBAL__sub_I_CHC_cpp=Module["
abort({“reason”:“Age needs to be below 150”,“hijackedStack”:“Error: Returned error: VM Exception while processing transaction: revert Age needs to be below 150 – Reason given: Age needs to be below 150.\n at Object.ErrorResponse (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-core-helpers\src\errors.js:29:1)\n at C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-core-requestmanager\src\index.js:140:1\n at C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\packages\provider\wrapper.js:112:1\n at XMLHttpRequest.request.onreadystatechange (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\web3-providers-http\src\index.js:96:1)\n at XMLHttpRequestEventTarget.dispatchEvent (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request-event-target.js:34:1)\n at XMLHttpRequest._setReadyState (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request.js:208:1)\n at XMLHttpRequest._onHttpResponseEnd (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request.js:318:1)\n at IncomingMessage. (C:\Users\VAIO-PC\AppData\Roaming\npm\node_modules\truffle\build\webpack:\~\xhr2-cookies\dist\xml-http-request.js:289:47)\n at IncomingMessage.emit (events.js:203:15)\n at IncomingMessage.EventEmitter.emit (domain.js:466:23)\n at endReadableNT (_stream_readable.js:1143:12)\n at process._tickCallback (internal/process/next_tick.js:63:19)”}). Build with -s ASSERTIONS=1 for more info.

C:\DOC\eth\PeopleProject>

Its hard to tell without the code but make sure that you are using async await properly.
Are you missing await keyword somewhere?

1 Like

The problem starts when I implemen the folowing code: , truffleAssert.errorType.REVERT
without this piece everything is working fine.

Value assignment solution:

const People = artifacts.require("People");
const truffleAssert = require("truffle-assertions");

contract("People", async function(accounts){

  let instance;

  before(async function(){
    instance = await People.deployed();
  });

  it("should set balance correctly", async function(){
    await instance.createPerson("Alex", 29, 190, {from: accounts[1], value: web3.utils.toWei("1", "ether")});
    let balanceTruffle = await instance.balance();
    let balanceGanache = await web3.eth.getBalance("0x3161444139fb73171D12e20670B179daeCf481A2");
    assert(balanceTruffle == balanceGanache, "Balances are not equal");
    });

  it("should the contract owner withdrawAll", async function(){
    let owner = accounts[0];
    let user = accounts[1];
    await truffleAssert.passes(instance.withdrawAll({from: owner}), truffleAssert.ErrorType.REVERT);
    let balanceTruffle = await instance.balance();
    assert(balanceTruffle == 0, "Balance is not zero");
  });
2 Likes

Hi @Johannes

Copy past your test code here and we ll help you, without your code we can’t see where is the error.
And use the preformatted text tag for more clarity thx :slight_smile:

Hi @ajcapo90

Your test is correct but why are you using an hardcoded address ? If you want to access your contract balance you can use

web3.eth.getBalance(instance.address)

It’s better than a static address

1 Like

This took me a little bit; however, I had an amazing eureka moment where the syntax finally began to make sense to me! Here’s my code:

contract ("People", async function(accounts){

  let instance;

  before(async function(){
    instance = await People.deployed();
  })
--
--
--
it("should increase contract's balance", async function(){
    let balance = await web3.eth.getBalance(People.address);
    await instance.createPerson("Waffles", 4, 20, {value: web3.utils.toWei("1", "ether"), from: accounts[1]});
    let newBalance = await web3.eth.getBalance(People.address);
    assert(balance < newBalance, "Balance did not update correctly");
  });

  it("should let contract owner withdraw balance", async function(){
    let ownerBalance = await web3.eth.getBalance(accounts[0]);
    await instance.createPerson("Waffles", 4, 20, {value: web3.utils.toWei("1", "ether"), from: accounts[1]});
    await instance.withdrawAll({from: accounts[0]});
    let newBalance = await web3.eth.getBalance(accounts[0]);
    assert(newBalance > ownerBalance, "Owner did not withdraw correctly");
  });

  it("should remove balance from contract", async function(){
    await instance.createPerson("Waffles", 4, 20, {value: web3.utils.toWei("1", "ether"), from: accounts[1]});
    let secondContractBalance = await web3.eth.getBalance(People.address);
    assert(secondContractBalance > 0, "Funds did not increase in contract");
    await instance.withdrawAll({from: accounts[0]});
    let thirdContractBalance = await web3.eth.getBalance(People.address);
    assert(thirdContractBalance == 0, "Contract funds did not leave correctly");
  });

  it("should match internal contract balance with blockchain contract balance", async function(){
    let varBalance = await instance.balance();
    let blockBalance = await web3.eth.getBalance(People.address);
    assert(varBalance == blockBalance), "I fucked this up from the start";
    await instance.createPerson("Waffles", 4, 19, {value: web3.utils.toWei("1", "ether"), from: accounts[1]});
    let newVarBal = await instance.balance();
    let newBlockBal = await web3.eth.getBalance(People.address);
    assert(newVarBal == newBlockBal), "I fucked this up at the end";
  });
});
1 Like
// BEFORE DELETING: create the person
    it("should create a person correctly", async function(){
      let instance = await People.deployed();
      await instance.createPerson("Lucy", 22, 180, {from: accounts[0], value: web3.utils.toWei("1", "ether")});  // Nótese que aquí no se necesita truffle-assertions
      let result = await instance.getPerson();
      assert(result.age.toNumber() === 22, "Owner was not able to create a person");
    });

    // FIRST STEP: NON-OWNER SHOULD FAIL AT DELETING
    it("shouldn't let a user other than owner delete a person", async function(){
      let instance = await People.deployed();
      await truffleAssert.fails(instance.deletePerson(accounts[3], {from:accounts[3]}), truffleAssert.ErrorType.REVERT);
    });

    // SECOND STEP: OWNER SHOULD SUCCEED AT DELETING
    it("should let the owner delete a person", async function(){
      let instance = await People.deployed();
      await truffleAssert.passes(instance.deletePerson(accounts[3], {from:accounts[0]}), truffleAssert.ErrorType.REVERT);
    });
1 Like
const People = artifacts.require("People");
const truffleAssert = require ("truffle-assertions");

contract("People", async function(){
it("should't create a person with age over 150 years ", async function(){
let instance = await People.deployed();
await truffleAssert.fails(instance.createPerson("Bob", 200, 190, {value: web3.utils.toWei("1", "ether")}), truffleAssert.errorType.REVERT);
})
});

Edit by gabba plz use the Preformatted text as i asked you, because it s really difficult to read your code

prefromatted_text-animated

hI @Johannes

It’s a typo

truffleAssert.errorType.REVERT

Should be

truffleAssert.ErrorType.REVERT

Edit:

Also do not forget to pass accounts as parameter of your contract function

contract("People", async function(accounts){

Hi @Glenn_CostaRica

I m not really sure to understand the purpose of your last test.
Why are you doing this

     await instance.deletePerson(accounts[0], {from:accounts[0]});
      let result = await instance.getPerson();

You are not testing the consequences of this test

1 Like

Thanks, it’s crazy how easily one can look over something like this. I was comparing my code countless times but I overlooked it.
Thank you very much😀
Greetings
Johannes

Yes, these kind of typos are the worst to find, I have spent countless hours solving mine eheh

1 Like

@gabba Man, that was a super silly mistake !! Really sorry!!! As a matter of fact, I had tried a lot of stuff, before finding my final answer. But, in the end, I forgot to erase the old meaningless lines of code !! Sorry for those two lines. They’re nothing in deed :slight_smile: :slight_smile: I just eliminated those two lines and ran my code <3
image

2 Likes

Took me a while to code the solution. I developed nothing new, but it helps me to give something to the console, so that I can see if I am doing the right thing.

  it("should not delete persons when this is not the owner", async function(){
    let instance = await People.deployed();
    await instance.createPerson("Bob", 80, 180, {from: accounts[1], value: web3.utils.toWei("1", "ether")});
    await truffleAssert.fails(instance.deletePerson(accounts[0], {from: accounts[1]}), truffleAssert.ErrorType.REVERT);
    //Person should still exist
    let person_exist = await (instance.getPerson({from: accounts[1]}));
    console.log("Person exist with following properties: " + person_exist.name +  " " + person_exist.age + " " + person_exist.height + " " + person_exist.senior);
  });
  it("should delete when this is the owner", async function(){
      let instance = await People.deployed();
      await instance.createPerson("Bob", 60, 180,{from: accounts[3],value: web3.utils.toWei("1", "ether")});
      await truffleAssert.passes(instance.deletePerson(accounts[3], {from: accounts[0]}));
      let person_exist = await (instance.getPerson({from: accounts[3]}));
      console.log("Person not existing: " + person_exist.name +  " " + person_exist.age + " " + person_exist.height + " " + person_exist.senior);
  })
});

During the assignment the following questions came up to my mind:
How is it possible to change the deployer of the contract? By default it is the first one, BUT what if we have not an arrays of accounts? Then you have to find out it in a different way. At first, I wanted to find out which address created/deployed the smart contract. I was not able to do it (in a short time, so I moved forward…). And the next question, how can I change the address of the contract owner by my own? For example the second account(address) should deploy the smart contract instead of the first one.

Hi @KryptoDr

If you want to change the account which deploy the contract you will have to modify the migration file which deploy your contract.

migrations/2_people_migration.js

const People = artifacts.require("People");

module.exports = function(deployer, network, accounts) {
    deployer.deploy(People, {from: accounts[1]});
}

Look at the deployer Api

1 Like

Thank you very much for your answer :slight_smile:

I have another question. When I click on contracts in Ganache and I deployed already a People contract then there is a smart contract address. When I am using now instance.address the addresses are different. In the transaction I can see that the instance.address is the same but what for an address is in Ganache in the contract tab?

PS: Another question. Why does address(this) does not work?

I m not sure to understand your question @KryptoDr can you provide a screenshot of the ganache contract page . And the address of your contract in your test ?
The address you are seeing in ganache is maybe your migration contract address.
Where are you calling address(this) ? if it’s in your smart contract it’s supposed to work .
Are you calling a getter to display this address in your test ?

1 Like

Here are my solution to the value assignment.

it("should increase the balance (internal variable) if a person is created", async function (){
  let balance_before = await instance.balance();
  await instance.createPerson("Bob", 80, 200, {value: web3.utils.toWei("1", "ether")});
  let balance_after = await instance.balance();
  assert((parseFloat(balance_before)+1000000000000000000) === parseFloat(balance_after), "balance was not increased");
});

it("should update the balance internal and on the blokchain", async function (){
  let balance_before = await instance.balance();
  let balance_before_blockchain = await web3.eth.getBalance(instance.address);
  console.log("Balance before " + balance_before);
  console.log("Balance before blockchain " + balance_before_blockchain);
  await instance.createPerson("Bob", 80, 200, {value: web3.utils.toWei("1", "ether")});
  let balance_after = await instance.balance();
  let balance_after_blockchain = await web3.eth.getBalance(instance.address);
  console.log("Balance after " + parseFloat(balance_after));
  console.log("Balance after blockchain " + parseFloat(balance_after_blockchain));
  assert(parseFloat(balance_after) === parseFloat(balance_after_blockchain), "both balances are not up to date");
});

it("should set the balance to zero if owner withdrawAll and both balances to zero", async function (){
  await instance.createPerson("Bob", 80, 200, {value: web3.utils.toWei("1", "ether")});
  await instance.createPerson("Bob", 70, 190, {value: web3.utils.toWei("1", "ether")});
  let balance_before = await instance.balance();
  console.log("Balance at start " + parseFloat(balance_before));
  let result = await instance.withdrawAll({from: accounts[0]});
  let balance_after_withdraw = await instance.balance();
  balance_after_withdraw = parseFloat(balance_after_withdraw);
  console.log("Balance after withdraw " + balance_after_withdraw);
  assert(parseFloat(balance_after_withdraw) === 0, "balance is not 0");
  let balance_after_blockchain = await web3.eth.getBalance(instance.address);
  console.log("Balance after withdraw bockchain " + balance_after_blockchain);
  assert(parseFloat(balance_after_withdraw) === parseFloat(balance_after_blockchain) , "balance are not equal");
})

Again I am checking with console.log a lot of things to see what I am doing. With PowerShell it is not very userfriendly. Does a development environment exist where I can check what variables are existing, which type they are of etc. ?

I am watching the solution and I recognize that we should have checked whether only the Owner is allowed to withdraw all funds. This part I have not implemented because I did not understand it in this way. Maybe below the videos the testing tasks should be described again and more clearly. I think this is also useful for every assignment videos. When there is a assignment describe it as a text below the videos, so that you don´t have to check the video again.

1 Like