Mocks

What are mocks?

Mocks are extensions to smart contracts that have all of the functionality of a fake with some extra goodies. Behind every mock is a real smart contract (with actual Solidity code!) of your choosing. You can modify the behavior of functions like a fake, or you can leave the functions alone and calls will pass through to your actual contract code. And, with a little bit of smock magic, you can even modify the value of variables within your contract! 🥳

When should I use a mock?

Generally speaking, mocks are more advanced versions of fakes. Mocks are most effectively used when you need some behavior of a real smart contract but still want the ability to modify things on the fly.

One powerful feature of a mock is that you can modify the value of variables within the smart contract. You could, for example, use this feature to test the behavior of a function that changes behavior depending on the value of a variable.

Using mocks

Initialization

Initialize with a contract name

const myContractFactory = await smock.mock('MyContract');
const myContract = await myContractFactory.deploy(...);

Take full advantage of typescript and typechain

await smock.mock<MyContract__factory>('MyContract');

Options

await smock.mock('MyContract', { ... }); // how to use

// options
{
  provider?: Provider; // initialize mock with a custom provider
}

Using features of fakes

Mocks can use any feature available to fakes. See the documentation of fakes for more information.

Call through

Calls go through to contract by default

await myMock.add(10);
await myMock.count(); // returns 10

myMock.count.returns(1);
await myMock.count(); // returns 1

Manipulating variables

Warning

This is an experimental feature and it is subject to API changes in the near future

Setting the value of a variable

await myMock.setVariable('myVariableName', 1234);

Setting the value of a struct

await myMock.setVariable('myStruct', {
  valueA: 1234,
  valueB: true,
});

Setting the value of a mapping (won’t affect other keys)

await myMock.setVariable('myMapping', {
  myKey: 1234
});

Setting the value of a nested mapping

await myMock.setVariable('myMapping', {
  myChildMapping: {
    myKey: 1234
  }
});

Setting the value of multiple variables

await myMock.setVariables({
  myVariableName1: 123,
  myVariableName2: true,
  myStruct: {
    valueA: 1234,
    valueB: false,
  },
  myMapping: {
    [myKey]: 1234
  }
})

Getting the value of an internal variable

Warning

This is an experimental feature and it does not support multidimensional or packed arrays

const myUint256 = await myMock.getVariable('myUint256VariableName');

Getting the value of an internal mapping given the value’s key

const myMappingValue = await myMock.getVariable('myMappingVariableName', [mappingKey]);

Getting the value of an internal nested mapping given the value’s keys

const myMappingValue = await myMock.getVariable('myMappingVariableName', [mappingKeyA, mappingKeyB]);