Unit Tests
Unit tests are small tests that test one piece of functionality within a contract.
How to Write Unit Testsβ
The following is an example of a unit test, written to test the increment contract. The contract has an increment
function, that increases a counter value by one on every invocation. The following test invokes that contract's function several times, and checks that the value increases by one.
#![cfg(test)]
use soroban_sdk::Env;
use crate::{IncrementContract, IncrementContractClient};
#[test]
fn test() {
let env = Env::default();
let contract_id = env.register(IncrementContract, ());
let client = IncrementContractClient::new(&env, &contract_id);
assert_eq!(client.increment(), 1);
assert_eq!(client.increment(), 2);
assert_eq!(client.increment(), 3);
}
Ref: https://github.com/stellar/soroban-examples/blob/main/increment/src/test.rs
In the test there's a full environment setup, used, and torn down in the test, and it happens fast. The Rust test harness runs all the tests for a contract in parallel and each will have its own isolated contract environment.
Most tests, even integration tests and fuzz tests, will look very similar to this unit test. They'll do four things:
-
Create an environment, the
Env
.let env = Env::default();
-
Register the contract(s) to be tested. Include as a second parameter any constructor parameters.
let contract_id = env.register(IncrementContract, ());
-
Invoke functions using the generated client.
let client = IncrementContractClient::new(&env, &contract_id);
client.increment() -
Assert the outcome.
assert_eq!(client.increment(), 1);
Tests are written in Rust, alongside the contract. Same tools. Same APIs. Same SDK. No context switching! Use your favorite Rust tools and libraries that you'd use for any Rust test.
The Env
created at the beginning of the test is not a simulation of the Soroban Environment. It's the same Soroban Environment that mainnet uses to execute contracts. There are only some minor differences: test utilities are enabled, and the storage backend is different.
Guides in this category:
ποΈ Unit Tests
Unit tests are small tests that test smart contracts.
ποΈ Mocking
Mocking dependency contracts in tests.
ποΈ Integration Tests
Integration testing uses dependency contracts instead of mocks.
ποΈ Fuzzing
Fuzzing and property testing to find unexpected behavior.
ποΈ Differential Tests
Differential testing detects unintended changes.
ποΈ Differential Tests with Test Snapshots
Differential testing using automatic test snapshots.
ποΈ Mutation Testing
Mutation testing finds code not tested.
ποΈ Test Authorization
Write tests that test contract authorization.
ποΈ Test Events
Write tests that test contract events.