Testing upgradeable contract with Mocha deployed via Truffle migrations

I have a Truffle migration file, much like the one from the example project:

// Load zos scripts and truffle wrapper function
const { scripts, ConfigManager } = require('@openzeppelin/cli');
const { add, push, create } = scripts;

async function deploy(options) {
  // Register v0 of MyContract in the zos project
  add({ contractsData: [{ name: 'MyContract_v0', alias: 'MyContract' }] });

  // Push implementation contracts to the network
  await push(options);

  // Create an instance of MyContract, setting initial value to 42
  await create(Object.assign({ contractAlias: 'MyContract', methodName: 'initialize', methodArgs: [42] }, options));

module.exports = function(deployer, networkName, accounts) {
  deployer.then(async () => {
    const { network, txParams } = await ConfigManager.initNetworkConfiguration({ network: networkName, from: accounts[1] })
    await deploy({ network, txParams })

I can run ganache-cli -f https://kovan.infura.io/v3/[key]@latest followed by truffle migrate --network local to run the migration.

But I’m using a different means of deployment in my test file, using TestHelper:

const { TestHelper } = require("@openzeppelin/cli");
const { defaultSender } = require("@openzeppelin/test-environment");

const MyContract = Contracts.getFromLocal("MyContract_v0");

describe("MyContract", () => {
   // An instance of ProxyAdminProject.
   let project;
   // An instance of MyContract_v0.
   let myContract;

   before(async function () {
      project = await TestHelper({ from: defaultSender });
      myContract = await project.createProxy(MyContract, {
         initMethod: "initialize",
         initArgs: [42],
   // tests...

There are two reasons why I prefer migrations over the CLI:

  1. My contracts have multiple initializer parameters.
  2. I’m forking Kovan to ganache, and because I don’t have access to archive state after a while, I need to restart ganache every so often.

Entering all of those parameters every so often is tedious, time-consuming, and prone to fat fingers. Using a migration would speed up deployment time, ensure all contracts and variables are properly initialized, and guarantee that public network deployments match those of my local tests.

I’m just unsure how to reference the contracts deployed via migration in my tests, and whether I need to modify my test script "test": "mocha --exit --recursive --no-timeout" if I’m using Truffle.

Is it safe to deploy and test in the manner above (migration file + a separate test deployment), or am I correct that both processes should be linked? If the latter, then how would I be able to use the instance of MyContract that was created and deployed in my migration, in my test?

After running the migration, the following in the beforeAll block produces TypeError: MyContract.deployed is not a function:

myContract = await MyContract.deployed();

and MyContract.address produces null.

1 Like

Hey @abcoathup, following up on this. Thanks!

1 Like

Hi @dtp5,

If you are deploying multiple times with several parameters, then scripting deployment is the way forward. Using truffle migrations is fine for this.
Please note, you won’t be able to interact with the contract using the OpenZeppelin CLI as the CLI only supports interaction when you deploy a contract with it.
For interaction you can either use a script or truffle console.

We had discussed previously about How to test upgradeable contracts?

If you haven’t already, I suggest you create unit tests just for your logic contract (as opposed to testing as an upgradeable contract using its proxy).

I wasn’t sure why you were forking Kovan. I assume you are building on top of other contracts and that this is the easiest/best way to create an environment that you can test with.

OpenZeppelin Test Environment spins up a local ganache powered blockchain rather than using an existing ganache. This means that you won’t be able to use truffle migrate to deploy your contracts for testing with OpenZeppelin Test Environment. Instead you can deploy in your tests.

OpenZeppelin Test Environment does support forking from an existing blockchain (see: fork and unlocked accounts)

Hi @dtp5,

Just wanted to follow up to see how you are going with your testing?

Hi @abcoathup, thanks for your thoughts and follow-up. In the end, it wasn’t worth the trouble switching to Truffle migrations at the expense of losing the CLI utility just to avoid paying for archive data in my ganache fork (my project does require testing against deployed contracts). Now that I have archive data, there’s no need to deploy multiple times with multiple initializer params, and I can continue using the CLI. Thanks!

1 Like