Skip to main content
Version: 5.x

Unit Tests

Testing contracts off-chain is done by cargo test and users can simply use the standard Rust routines of creating unit test modules within the ink! project:

mod tests {
use super::*;

fn my_test() { ... }

Test instances of contracts can be created with something like:

let contract = MyContract::my_constructor(a, b);

Messages can simply be called on the returned instance as if MyContract::my_constructor returns a Self instance.

See the flipper example.

Integration Tests

For integration tests, the test is annotated with our #[ink::test] attribute instead of #[test]. Our attribute denotes that the test is then executed in a simulated, mocked blockchain environment. here are functions available to influence how the test environment is configured (e.g. setting a specified balance of an account to simulate how a contract would behave when interacting with it).

If you annotate a test with the #[ink::test] attribute it will be executed in a simulated environment, similar to as it would be run on-chain. You then have fine-grained control over how a contract is called; for example you can influence the block advancement, the value transferred to it, by which account it is called, which storage it is run with, etc..

See the examples/erc20 contract on how to utilize those or the documentation for details.

At the moment there are some known limitations to our off-chain environment, and we are working on making it behave as close to the real chain environment as possible.


One limitation of the off-chain testing framework is that it currently only supports a DefaultEnvironment.

See here for an explanation of what an environment is.

How do you find out if your test requires the off-chain environment?

Normally if the test recursively uses or invokes some contract methods that call a method defined in self.env() or Self::env().

An example is the following:

let caller: AccountId = self.env().caller();


mod tests {
// Conventional unit test that works with assertions.
fn test1() {
// test code comes here as usual

// Conventional unit test that returns some Result.
// The test code can make use of operator-`?`.
fn test2() -> Result<(), ink::env::Error> {
// test code that returns a Rust Result type