This content is being translated and will be available here when ready.
Testing Your Program
Thorough testing prevents financial losses, builds user trust, and ensures your program behaves correctly under all conditions.
TypeScript Tests
TypeScript testing is the most common approach since you'll need TypeScript for your dApp client anyway. This lets you develop tests and client code simultaneously.
We covered client-side setup in detail here.
TypeScript tests offer key advantages:
- Mirror real client interactions
- Test complex workflows and edge cases
- Provide immediate feedback on API changes
- Validate success and error scenarios
Run tests with:
anchor test
Mollusk Tests
When you need granular control over testing environments or complex program state setup, Mollusk provides the solution.
Mollusk is a Rust testing framework built specifically for Solana programs. It enables you to:
- Test program logic in isolation without network overhead
- Set up complex account states 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 tests using:
anchor test
LiteSVM Tests
When you need the same granular control over your program state, like Mollusk, but in Typescript LiteSVM provides the optimal solution.
LiteSVM is a lightweight testing framework that runs the Solana Virtual Machine directly in your test process. It enables you to:
- Execute tests significantly faster than traditional frameworks like
solana-program-test
- Manipulate account states and sysvars with precision
- Test across multiple languages: TypeScript, Rust, and Python
- Mock complex blockchain conditions and edge cases effortlessly
LiteSVM eliminates validator overhead by embedding the VM within your tests, delivering the speed needed for rapid development cycles without sacrificing testing accuracy.
We covered LiteSVM testing thoroughly here.
You can set up your Anchor provider and use the client-side setup we saw previously with the anchor-litesvm
package.
Installe the anchor-litesvm
package.
npm install git:https://github.com/LiteSVM/anchor-litesvm
Then change the default Anchor provider to LiteSVMProvider
like this:
import { fromWorkspace, LiteSVMProvider } from "anchor-litesvm";
test("anchor", async () => {
const client = fromWorkspace("target/types/<program-name>.ts");
const provider = new LiteSVMProvider(client);
const program = new Program<Puppet>(IDL, provider);
// program.methods..
})
Running a Local Validator
Mirror mainnet behavior locally using a validator that acts as your personal blockchain sandbox. This happens automatically when you set your cluster to localnet.
The local validator operates a simplified Solana ledger with native programs pre-installed. By default, it only stores test data and lacks access to existing mainnet accounts—limiting testing with established protocols.
Configuring Your Local Validator
Customize your validator in Anchor.toml
under the [test]
section:
[test]
startup_wait = 10000
The startup_wait
flag delays validator startup, useful when cloning multiple accounts that increase load time.
Cloning Mainnet Accounts
Clone existing mainnet accounts and programs 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 clone
section copies accounts from the specified cluster. When an account links to a program managed by the "BPF upgradeable loader", Anchor automatically clones the associated program data account.
Loading Local Account Data
Load local accounts from JSON files using the account
flag:
[[test.validator.account]]
address = "Ev8WSPQsGb4wfjybqff5eZNcS3n6HaMsBkMk9suAiuM"
filename = "some_account.json"
This approach works well for testing with pre-configured account states or specific configurations that don't exist on mainnet.
Running Surfnet
Testing Solana programs that rely on Cross-Program Invocations (CPIs) traditionally requires developers to dump accounts and programs from mainnet, like we saw in the Local Validator section.
This process works for a few accounts, but becomes completely unfeasible when testing CPIs into complex programs like Jupiter, which can depend on 40+ accounts and 8+ programs.
Surfnet serves as a drop-in replacement for solana-test-validator that enables developers to simulate programs locally using mainnet accounts fetched on-demand
To use it, just install surfpool using the official Installation Page and then run:
surfpool start
You can now connect to Surfnet by targeting the local validator:
import { Connection } from "@solana/web3.js";
const connection = new Connection("http://localhost:8899", "confirmed");
We covered Surfnet setup and usage thoroughly here.