@defi-wonderland/smock-foundry
v1.5.0
Published
Smock-style mocks for Foundry projects
Downloads
518
Keywords
Readme
Smock Foundry
A plugin for foundry that automatically generates Solidity mocks for every contract in your project.
Features
- Get rid of your folder of "mock" contracts and just use foundry.
- Keep your tests simple with straightforward mock functions.
- Mock up external calls and internal variables in a beautiful and orderly fashion.
Installation
You can install the plugin via yarn:
yarn add @defi-wonderland/smock-foundry --save-dev
Basic Usage
Creating mocks
To generate the mock contracts all you have to do is run:
yarn smock-foundry --contracts solidity/contracts
The smock-foundry
command accepts the following options:
| Option | Default | Notes |
| ----------- | -------------- | ---------------------------------------------------------- |
| contracts
| — | The path to the solidity contracts to mock |
| root
| .
| The path to the root of the project |
| mocks
| ./test/smock
| The path to the generated mock contracts |
| ignore
| [] | A list of directories to ignore, e.g. --ignore libraries
|
Be sure to gitignore
the generated smock directory.
Using mocks
Let's say you have a Greeter
contract in your project at contracts/Greeter.sol
:
contract Greeter {
string internal _greeting;
constructor(string memory greeting) {
_greeting = greeting;
}
function greet() public view returns (string memory) {
return _greeting;
}
}
After running the generator, you will have a mock contract located at ${mocks}/contracts/MockGreeter.sol
:
contract MockGreeter is Greeter {
function mock_call_greet(string memory __greeting) external {
// Mocks the greet() function calls
}
function set__greeting(string memory greeting) public {
// Sets the value of `greeting`
}
}
The next step would be importing the mock contract in your unit tests, deploying it and allowing it to use the cheatcodes, specifically vm.mockCall
.
import 'forge-std/Test.sol';
import { MockGreeter } from '/path/to/smock/contracts/MockGreeter.sol';
import { SmockHelper } from '/path/to/smock/SmockHelper.sol';
contract BaseTest is Test, SmockHelper {
MockGreeter public greeter;
function setUp() public {
// The `deployMock` call is equivalent to
// address _greeterAddress = address(new MockGreeter('Hello'));
// vm.label(_greeterAddress, 'Greeter');
// vm.allowCheatcodes(_greeterAddress);
// return _greeterAddress;
greeter = MockGreeter(
deployMock('Greeter', type(Greeter).creationCode, abi.encode('Hello'))
);
}
}
Then enjoy the wonders of mocking:
// Mock the `greet` function to return 'Hola' instead of 'Hello'
greeter.mock_call_greet('Hola');
// Or you can achieve the same by setting the internal variable
greeter.set__greeting('Hola');
Gotchas
- Please, note that if you want to mock
internal
functions, you must make themvirtual
. The tool will not generate mocks for internal functions that are not virtual. - Cannot set
private
variables and mockprivate
functions. - Mocking of structs containing mappings is not supported.
- Mocking of multi-dimensional arrays of structs is not supported.
Licensing
The primary license for Smock Foundry is MIT, see LICENSE
.
Contributors
Maintained with love by Wonderland. Made possible by viewers like you.