3

background

I have written an ethereum smart-contract in the Solidity language. In order to test things, I can run a local node using Ganache and deploy my contract on it using truffle migrate.

requirements

I want to test my contract using JavaScript. I want to create a new instance of my contract for each test.

what i've tried

I created a test file tests/test.js in my project:

const expect = require('chai').expect

const Round = artifacts.require('Round')


contract('pledgersLength1', async function(accounts) {
    it('1 pledger', async function() {
        let r = await Round.deployed()
        await r.pledge(5)
        let len = (await r.pledgersLength()).toNumber()
        expect(len).to.equal(1)
    })
})
contract('pledgersLength2', async function(accounts) {
    it('2 pledgers', async function() {
        let r = await Round.deployed()
        await r.pledge(5)
        await r.pledge(6)
        let len = (await r.pledgersLength()).toNumber()
        expect(len).to.equal(2)
    })
})

I run it with truffle test. It's basically Mocha, but truffle defines artifacts for you with a JavaScript connection to the smart contracts.

The truffle contract function is almost the same as Mocha's describe function, with a small change that I don't understand! I assumed that contract would make my contract new each time. It doesn't. Perhaps I can use something like new Round() instead of Round.deployed(), but I just don't know how.

The solution does not have to use truffle.

mareoraft
  • 3,474
  • 4
  • 26
  • 62
  • Are you sure it is not the same contract? On their site they claim that is will be a new contract instance in every `describe` function. How do you know that is the same instance? – nikos fotiadis Oct 07 '18 at 22:07
  • 1
    Check this Twitter thread — https://twitter.com/zulhhandyplast/status/1026181801239171072 – Zulhilmi Zainudin Oct 08 '18 at 05:40
  • @nikosfotiadis I am sure. The way that I know is probably irrelevant to the question, but if you try to pledge the same amount twice, the contract will error. So in the example I typed above, I get an error when I expect to not get an error. – mareoraft Oct 08 '18 at 18:34
  • @ZulhilmiZainudin Yes, using `.new()` instead of `.deployed()` is working like a charm! That should really be added to the truffle documentation. Could you post it as an answer? – mareoraft Oct 08 '18 at 19:16
  • I'm glad it helped. I've posted my answer. Appreciate if you can upvote and accept it. – Zulhilmi Zainudin Oct 08 '18 at 21:47

1 Answers1

5

Please note that .new and .deployed are not the same. See what I've found here.

Follow this example and it should solve your problem:

// Path of this file: ./test/SimpleStorage.js
var simpleStorage = artifacts.require("./SimpleStorage.sol");

contract('SimpleStorage', function(accounts) {

  var contract_instance;

  before(async function() {
    contract_instance = await simpleStorage.new();
  });

  it("owner is the first account", async function(){
    var owner = await contract_instance.owner.call();
    expect(owner).to.equal(accounts[0]);
  });

});

The .new keyword will deploy an instance of your contract in a new context.

But, .deployed will actually use the contract that you have deployed earlier i.e. when you are using truffle migrate command.

In the context of unit test, it's better to use .new so that you will always start with fresh contract.

Zulhilmi Zainudin
  • 9,017
  • 12
  • 62
  • 98