4.0.4 • Published 7 months ago

@ethereum-waffle/mock-contract v4.0.4

Weekly downloads
13,385
License
MIT
Repository
github
Last release
7 months ago

Ethereum Waffle

CircleCI npm.io

@ethereum-waffle/mock-contract

Library for mocking smart contract dependencies during unit testing.

Warning

@ethereum-waffle/mock-contract is an experimental package. Breaking changes will not result in a new major version.

Installation

In the current version of waffle (v2.x.x) you will install this package as a dependency of the main waffle package - ethereum-waffle.

yarn add --dev ethereum-waffle
npm install --save-dev ethereum-waffle

If you want to use this package directly please install it via:

yarn add --dev @ethereum-waffle/mock-contract
npm install --save-dev @ethereum-waffle/mock-contract

Usage

Create an instance of a mock contract providing the ABI/interface of the smart contract you want to mock:

const {deployMockContract} = require('@ethereum-waffle/mock-contract');

...

const mockContract = await deployMockContract(wallet, contractAbi);

Mock contract can now be passed into other contracts by using the address attribute.

Return values for mocked functions can be set using:

await mockContract.mock.<nameOfMethod>.returns(<value>)
await mockContract.mock.<nameOfMethod>.withArgs(<arguments>).returns(<value>)

Methods can also be set up to be reverted using:

await mockContract.mock.<nameOfMethod>.reverts()
await mockContract.mock.<nameOfMethod>.withArgs(<arguments>).reverts()

Example

The example below illustrates how mock-contract can be used to test the very simple AmIRichAlready contract.

pragma solidity ^0.6.0;

interface IERC20 {
    function balanceOf(address account) external view returns (uint256);
}

contract AmIRichAlready {
    IERC20 private tokenContract;
    uint private constant RICHNESS = 1000000 * 10 ** 18;

    constructor (IERC20 _tokenContract) public {
        tokenContract = _tokenContract;
    }

    function check() public view returns (bool) {
        uint balance = tokenContract.balanceOf(msg.sender);
        return balance > RICHNESS;
    }
}

We are mostly interested in the tokenContract.balanceOf call. Mock contract will be used to mock exactly this call with values that are significant for the return of the check() method.

const {use, expect} = require('chai');
const {ContractFactory, utils} = require('ethers');
const {MockProvider} = require('@ethereum-waffle/provider');
const {waffleChai} = require('@ethereum-waffle/chai');
const {deployMockContract} = require('@ethereum-waffle/mock-contract');

const IERC20 = require('../build/IERC20');
const AmIRichAlready = require('../build/AmIRichAlready');

use(waffleChai);

describe('Am I Rich Already', () => {
  async function setup() {
    const [sender, receiver] = new MockProvider().getWallets();
    const mockERC20 = await deployMockContract(sender, IERC20.abi);
    const contractFactory = new ContractFactory(AmIRichAlready.abi, AmIRichAlready.bytecode, sender);
    const contract = await contractFactory.deploy(mockERC20.address);
    return {sender, receiver, contract, mockERC20};
  }

  it('returns false if the wallet has less then 1000000 coins', async () => {
    const {contract, mockERC20} = await setup();
    await mockERC20.mock.balanceOf.returns(utils.parseEther('999999'));
    expect(await contract.check()).to.be.equal(false);
  });

  it('returns true if the wallet has at least 1000000 coins', async () => {
    const {contract, mockERC20} = await setup();
    await mockERC20.mock.balanceOf.returns(utils.parseEther('1000001'));
    expect(await contract.check()).to.equal(true);
  });

  it('reverts if the ERC20 reverts', async () => {
    const {contract, mockERC20} = await setup();
    await mockERC20.mock.balanceOf.reverts();
    await expect(contract.check()).to.be.revertedWith('Mock revert');
  });

  it('returns 1000001 coins for my address and 0 otherwise', async () => {
    const {contract, mockERC20, sender, receiver} = await setup();
    await mockERC20.mock.balanceOf.returns('0');
    await mockERC20.mock.balanceOf.withArgs(sender.address).returns(utils.parseEther('1000001'));

    expect(await contract.check()).to.equal(true);
    expect(await contract.connect(receiver.address).check()).to.equal(false);
  });
});

Special thanks

Special thanks to @spherefoundry for creating the original Doppelganger project.

4.0.4-dev.238c11c

7 months ago

4.0.4-dev.efd5f2a

7 months ago

4.0.4

1 year ago

4.0.3

1 year ago

4.0.1

2 years ago

4.0.2

2 years ago

4.0.0-alpha.21

2 years ago

4.0.0-alpha.9

2 years ago

4.0.0-alpha.17

2 years ago

4.0.0-alpha.16

2 years ago

4.0.0-alpha.15

2 years ago

4.0.0-alpha.14

2 years ago

4.0.0-alpha.19

2 years ago

4.0.0-alpha.18

2 years ago

4.0.0-alpha.17.4

2 years ago

4.0.0-alpha.13

2 years ago

4.0.0-alpha.12

2 years ago

4.0.0-alpha.11

2 years ago

4.0.0-alpha.10

2 years ago

4.0.0-alpha.20

2 years ago

4.0.0-alpha.7

2 years ago

4.0.0-alpha.8

2 years ago

4.0.0-alpha.5

2 years ago

4.0.0-alpha.6

2 years ago

4.0.0-alpha.3

2 years ago

4.0.0-alpha.4

2 years ago

4.0.0-alpha.1

2 years ago

4.0.0-alpha.2

2 years ago

3.4.4

2 years ago

3.3.1

2 years ago

4.0.0-alpha.0

2 years ago

3.3.0

3 years ago

3.2.2

3 years ago

3.2.1

3 years ago

3.2.0

4 years ago

3.1.2

4 years ago

3.1.1

4 years ago

3.1.0

4 years ago

3.0.3

4 years ago

3.0.2

4 years ago

3.0.1

4 years ago

3.0.0

4 years ago

3.0.0-beta.3

4 years ago

3.0.0-beta.2

4 years ago

2.5.1

4 years ago

2.5.0

4 years ago

3.0.0-beta.1

4 years ago

2.4.1

4 years ago