Testing upgradeable contracts with OZ instead of truffle

Is it possible to test upgradeable contracts without running truffle test?

When I try using the TestHelper and ZWeb3, I get problems saying web3 isn’t defined and I’m not sure how I can pass a provider?

1 Like

Hi @emobe,

We can use OpenZeppelin Test Environment and test upgradeable contracts.
We can get web3 from OpenZeppelin Test Environment

const { accounts, defaultSender, contract, web3, provider, isHelpersConfigured } = require('@openzeppelin/test-environment');

Below is an example contract (taken from the Learn documentation), along with tests for the logic contract (https://docs.openzeppelin.com/learn/writing-automated-tests) and an upgradeable version of the tests.

Box.sol

// contracts/Box.sol
pragma solidity ^0.5.0;

contract Box {
    uint256 private value;

    // Emitted when the stored value changes
    event ValueChanged(uint256 newValue);

    // Stores a new value in the contract
    function store(uint256 newValue) public {
        value = newValue;
        emit ValueChanged(newValue);
    }

    // Reads the last stored value
    function retrieve() public view returns (uint256) {
        return value;
    }
}

Box.test.js (test logic contract)

// contracts/Box.sol
pragma solidity ^0.5.0;

contract Box {
    uint256 private value;

    // Emitted when the stored value changes
    event ValueChanged(uint256 newValue);

    // Stores a new value in the contract
    function store(uint256 newValue) public {
        value = newValue;
        emit ValueChanged(newValue);
    }

    // Reads the last stored value
    function retrieve() public view returns (uint256) {
        return value;
    }
}

Box.upgradeable.test.js

// test/Box.upgradeable.test.js

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

const { TestHelper } = require('@openzeppelin/cli');
const { Contracts, ZWeb3 } = require('@openzeppelin/upgrades');

// Import utilities from Test Helpers
const { BN, expectEvent, expectRevert } = require('@openzeppelin/test-helpers');

ZWeb3.initialize(web3.currentProvider);

const Box = Contracts.getFromLocal('Box');

describe('Box', function () {
  const [ owner, other ] = accounts;

  const value = '42';

  beforeEach(async function () {
    this.project = await TestHelper();
    this.proxy = await this.project.createProxy(Box);
  });

  it('retrieve returns a value previously stored', async function () {
    await this.proxy.methods.store(42).send({ from: owner });

    // Use large integer comparisons
    expect(await this.proxy.methods.retrieve().call()).to.be.bignumber.equal(value);
  });

  it('store emits an event', async function () {
    const receipt = await this.proxy.methods.store(42).send({ from: owner });

    // Test that a ValueChanged event was emitted with the new value
    expectEvent(receipt, 'ValueChanged', { newValue: value });
  });
});
1 Like

Ah, you life saver! I didn’t know it came with it’s own. Thanks a lot.

1 Like