Testing your Program
Thorough testing is essential before mainnet deployment to identify potential bugs and vulnerabilities.
Well-tested programs prevent financial losses, build user trust, and ensure applications behave correctly under various conditions.
Typescript Tests
Testing with TypeScript is the most common approach since you'll need TypeScript implementation for your dApp anyway. This approach allows you to develop tests and client-side code simultaneously.
We covered client-side setup in detail here.
TypeScript tests provide several advantages:
- Mirror actual client interactions your dApp will perform
- Test complex user workflows and edge cases
- Provide immediate feedback on API changes
- Validate both successful operations and error handling
Run your tests with:
anchor test
Mollusk Tests
When setting up complex program states or requiring intricate onchain interactions proves difficult, Mollusk provides more granular control over the testing environment.
Mollusk is a Rust testing framework designed specifically for Solana programs that enables you to:
- Test program logic in isolation without network overhead
- Set up complex account states and program conditions easily
- Run tests faster than full integration tests
- Mock specific blockchain conditions and edge cases
We covered Mollusk testing thoroughly here.
Create a new Anchor program with Mollusk:
anchor init <name-of-the-project> --test-template mollusk
Run your tests using:
anchor test
Running a Local Validator
You can mirror mainnet behavior on localnet using a local validator. This happens automatically when you set your cluster to localnet, but additional configuration enables more comprehensive testing scenarios.
A local validator acts as your personal blockchain node, providing a sandbox environment for testing without connecting to live networks. It operates a local test ledger: a simplified Solana ledger with all native programs pre-installed and various features enabled.
This ledger is fully customizable for your testing needs.
By default, the local validator only stores data created during tests. It lacks access to existing mainnet accounts and programs, which can limit testing scenarios when interacting with established protocols or account states.
Configuring Your Local Validator
Add configuration fields in your Anchor.toml
file under the [test]
section to customize your local validator:
[test]
startup_wait = 10000
The startup_wait flag delays solana-test-validator
startup. This delay proves beneficial when cloning multiple accounts, extending startup time to accommodate increased load and ensure proper account loading.
Cloning Mainnet Accounts
Clone existing mainnet accounts and programs to your local validator using [test.validator]
configuration:
[test.validator]
url = "https://api.mainnet-beta.solana.com"
[[test.validator.clone]]
address = "7NL2qWArf2BbEBBH1vTRZCsoNqFATTddH6h8GkVvrLpG"
[[test.validator.clone]]
address = "2RaN5auQwMdg5efgCaVqpETBV8sacWGR8tkK4m9kjo5r"
[[test.validator.clone]]
address = "metaqbxxUerdq28cj1RbAWkYQm3ybzjb6a8bt518x1s"
The [test.validator.clone]
section clones accounts from the specified cluster to your test environment. When an account links to a program managed by the "BPF upgradeable loader," Anchor automatically clones the associated program data account, ensuring complete program state availability locally.
Loading Local Account Data
Integrate local accounts from JSON files into your validator setup using the [test.validator.account]
flag:
[[test.validator.account]]
address = "Ev8WSPQsGb4wfjybqff5eZNcS3n6HaMsBkMk9suAiuM"
filename = "some_account.json"
This approach proves useful when testing with pre-configured account states saved locally or specific account configurations that don't exist on mainnet.