Use of contract methods after initialization not possible

I do some tests for my application working with smart-contracts, for that I use the test-environment module provided by openzepplin. But I don’t really understand how it works, when I put it in my application I use the web3 module to configure and use my method in my contract, but with test-environment, the methods are not recognized and I cannot use them.

:computer: Environment
web3 : 6.13.4
@openzeppelin/contract-loader : 0.5.0
@openzeppelin/test-environment : 0.1.1

:memo:Details
in my app i run a method with : contract.methods.owner()
but in my test, I only can use contract.owner() directly, without .methods, but the methods of my API are working fine with the first method and can’t work without the .methods search in the contract instead of the test.

:1234: Code to reproduce

what is use for test but not working with my app:

  beforeEach(async function {
    this.myContract = await MyContract.new({ from: owner });
  });

  it('the deployer is the owner', async function () {
    expect(await this.myContract.owner()).to.equal(owner);
  });

What I want to do: (add .methods between the contract and the methods use like in web3)

  beforeEach(async function {
    this.myContract = await MyContract.new({ from: owner });
  });

  it('the deployer is the owner', async function () {
    expect(await this.myContract.methods.owner()).to.equal(owner);
  });

Error:

  1) owner
       deployer is owner:
     TypeError: myContract.methods.owner is not a function
      at Context.<anonymous> (test/contract.spec.js:22:53)
      at processImmediate (internal/timers.js:456:21)

without that I can’t test my API. if someone can tell me how to work around or if I miss somethings

2 Likes

Hi @vincent,

If I understand your question correctly, I assume you want to create a new contract using web3.eth.Contract and then make call and send on methods.

I am not sure of the correct syntax either.

// Load dependencies
const { web3, accounts, contract } = require('@openzeppelin/test-environment');
const { expect } = require('chai');

// Load compiled artifacts
const MyContract = contract.fromArtifact('MyContract');

// Start test block
describe('MyContract', function () {
  const [ owner ] = accounts;

  beforeEach(async function () {
    // Deploy a new MyContract contract for each test
    //web3.eth.Contract(MyContract.abi);
  });

  // Test case
  it('is owned', async function () {
    expect(await this.contract.methods.owner().call()).to.equal(owner);
  });
});
1 Like

Hey @vincent! Thank you for trying test-environement!
There are two web3 contract abstractions: Truffle and Web3.js. By default test-environment is configured to use Truffle abstraction that is why this.myContract.owner() works. In order to switch to web3.js contract abstraction and use contract.methods.owner() you need to configure test-environment.config.js file like this:

// test-environment.config.js

module.exports = {
  accounts: {
    amount: 10, // Number of unlocked accounts
    ether: 100, // Initial balance of unlocked accounts (in ether)
  },

  contracts: {
    type: 'web3', // Contract abstraction to use: 'truffle' for @truffle/contract or 'web3' for web3-eth-contract
    defaultGas: 6e6, // Maximum gas for contract calls (when unspecified)

    // Options available since v0.1.2
    defaultGasPrice: 20e9, // Gas price for contract calls (when unspecified)
    artifactsDir: 'build/contracts', // Directory where contract artifacts are stored
  },

  blockGasLimit: 8e6, // Maximum gas per block
};

You can learn more here. Let me know how it goes for you!

2 Likes

You also have to deploy your contracts using web3.js deploy method.

  this.myContract = await MyContract. deploy().send({ from: owner} );
1 Like

Thank you for your clear and constructive response. After your reading and various tests, I understood the operation and the configuration to set up to use your module. Thank you for your help. For the sake of clarity I put here the code that I wrote so that it works:

const { accounts, contract } = require('@openzeppelin/test-environment');
const [owner] = accounts;
const MyContract = contract.fromArtifact('contract');

const instance = await MyContract.deploy().send({ from: owner} );

don’t forget to define the type of contract in the test-environment.config.js

type: 'web3'

Now you can use the web3 methods on the contract like :

await instance.methods.owner().call({from: owner});

3 Likes

@vincent, that is exactly what I meant. Happy to hear it worked for you and enjoy blazing fast testing with Test Environment!

2 Likes