> ## Documentation Index
> Fetch the complete documentation index at: https://neardocs-docs-2123-js-error-prone-collections.mintlify.site/llms.txt
> Use this file to discover all available pages before exploring further.

# Integration Tests

> Learn how to write and run integration tests for NEAR smart contracts using Sandbox testing and realistic blockchain environments.

export const Github = ({url, start, end, fname, withSourceLink = true}) => {
  const [code, setCode] = useState(null);
  function toRaw(ref) {
    const fullUrl = ref.slice(ref.indexOf('https'));
    const [url] = fullUrl.split('#');
    const [org, repo, , branch, ...pathSeg] = new URL(url).pathname.split('/').slice(1);
    return `https://raw.githubusercontent.com/${org}/${repo}/${branch}/${pathSeg.join('/')}`;
  }
  async function fetchCode(url, fromLine, toLine) {
    let res;
    if (typeof window !== 'undefined') {
      const validUntil = localStorage.getItem(`${url}-until`);
      if (validUntil && Number(validUntil) > Date.now()) {
        res = localStorage.getItem(url);
      }
    }
    if (!res) {
      try {
        res = await (await fetch(url)).text();
        if (typeof window !== 'undefined') {
          localStorage.setItem(url, res);
          localStorage.setItem(`${url}-until`, String(Date.now() + 60000));
        }
      } catch {
        return 'Error fetching code, please try reloading';
      }
    }
    let body = res.split('\n');
    const from = fromLine ? Number(fromLine) - 1 : 0;
    const to = toLine ? Number(toLine) : body.length;
    body = body.slice(from, to);
    const precedingSpace = body.reduce((prev, line) => {
      if (line.length === 0) return prev;
      const spaces = line.match(/^\s+/);
      if (spaces) return Math.min(prev, spaces[0].length);
      return 0;
    }, Infinity);
    return body.map(line => line.slice(precedingSpace === Infinity ? 0 : precedingSpace)).join('\n');
  }
  function buildSourceUrl(url, start, end) {
    const base = url.split('#')[0];
    if (start && end) return `${base}#L${start}-L${end}`;
    if (start) return `${base}#L${start}`;
    return base;
  }
  useEffect(() => {
    const rawUrl = toRaw(url);
    fetchCode(rawUrl, start, end).then(res => setCode(res));
  }, [url, start, end]);
  const sourceUrl = buildSourceUrl(url, start, end);
  const startLine = start ? Number(start) : 1;
  const fileName = fname ?? sourceUrl.split('/').pop();
  return <div className="rounded-[0.625rem] border border-[#d0d7de] dark:border-[#30363d] overflow-hidden my-5 text-[0.8125rem] font-mono shadow-sm dark:shadow-[0_4px_24px_rgba(0,0,0,0.18)]">

      {}
      <div className="flex items-center justify-between py-2 px-[0.875rem] bg-[#f6f8fa] dark:bg-[#161b22] border-b border-[#d0d7de] dark:border-[#30363d]">
        <div className="flex items-center gap-2 text-[#656d76] dark:text-[#8b949e]">
          <svg width="15" height="15" viewBox="0 0 24 24" fill="currentColor">
            <path d="M12 0C5.37 0 0 5.37 0 12c0 5.31 3.435 9.795 8.205 11.385.6.105.825-.255.825-.57 0-.285-.015-1.23-.015-2.235-3.015.555-3.795-.735-4.035-1.41-.135-.345-.72-1.41-1.23-1.695-.42-.225-1.02-.78-.015-.795.945-.015 1.62.87 1.845 1.23 1.08 1.815 2.805 1.305 3.495.99.105-.78.42-1.305.765-1.605-2.67-.3-5.46-1.335-5.46-5.925 0-1.305.465-2.385 1.23-3.225-.12-.3-.54-1.53.12-3.18 0 0 1.005-.315 3.3 1.23.96-.27 1.98-.405 3-.405s2.04.135 3 .405c2.295-1.56 3.3-1.23 3.3-1.23.66 1.65.24 2.88.12 3.18.765.84 1.23 1.905 1.23 3.225 0 4.605-2.805 5.625-5.475 5.925.435.375.81 1.095.81 2.22 0 1.605-.015 2.895-.015 3.3 0 .315.225.69.825.57A12.02 12.02 0 0 0 24 12c0-6.63-5.37-12-12-12z" />
          </svg>
          <span className="text-xs font-medium text-[#1f2328] dark:text-[#e6edf3]">
            {fileName}
          </span>
        </div>
        {start && end && <span className="text-[0.6875rem] text-[#656d76] dark:text-[#8b949e] bg-[#eaeef2] dark:bg-[#21262d] border border-[#d0d7de] dark:border-[#30363d] rounded-full py-0.5 px-2">
            Lines {start}–{end}
          </span>}
      </div>

      {}
      <div className="overflow-auto max-h-[480px] bg-white dark:bg-[#0d1117] [&_tr]:border-b-0 [&_td]:border-b-0">
        {code === null ? <div className="py-5 px-4 text-xs text-[#656d76] dark:text-[#6e7681]">
            Loading...
          </div> : <table className="w-full border-collapse leading-[1.6]">
            <tbody>
              {code.split('\n').map((line, i) => <tr key={i} className="align-top border-0">
                  <td style={{
    minWidth: '60px'
  }} className="select-none pl-2 pr-3 text-right text-[0.7rem] text-[#8c959f] dark:text-[#3d444d] w-[1%] whitespace-nowrap border-r border-0 border-r-[#d0d7de] dark:border-r-[#21262d]">
                    {startLine + i}
                  </td>
                  <td className="pl-4 pr-6 text-[0.8125rem] text-[#1f2328] dark:text-[#e6edf3] whitespace-pre">
                    {line || ' '}
                  </td>
                </tr>)}
            </tbody>
          </table>}
      </div>

      {}
      {withSourceLink && <div className="flex justify-end py-1.5 px-[0.875rem] bg-[#f6f8fa] dark:bg-[#161b22] border-t border-[#d0d7de] dark:border-[#21262d]">
          <a href={sourceUrl} target="_blank" rel="noreferrer noopener" className="text-[0.6875rem] font-medium text-[#656d76] dark:text-[#8b949e] no-underline flex items-center gap-[0.3rem] hover:text-[#1f2328] dark:hover:text-[#e6edf3] transition-colors">
            View on GitHub
            <svg width="11" height="11" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2.5" strokeLinecap="round" strokeLinejoin="round">
              <path d="M18 13v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V8a2 2 0 0 1 2-2h6" />
              <polyline points="15 3 21 3 21 9" />
              <line x1="10" y1="14" x2="21" y2="3" />
            </svg>
          </a>
        </div>}
    </div>;
};

Integration tests enable you to deploy a contract in the NEAR `testnet` or a local `sandbox` and create test users to interact with it. This way, you can thoroughly test your contract in a realistic environment.

Moreover, when using the local `sandbox` you gain complete control of the network:

1. Create test `Accounts` and manipulate their `State` and `Balance`.
2. Simulate errors on callbacks.
3. Control the time-flow and fast-forward into the future (Rust ready, TS coming soon).

In NEAR, integration tests are implemented using a framework called **Sandbox**. Sandbox comes in two flavors: [🦀 Rust](https://github.com/near/near-sandbox-rs) and [🌐 Typescript](https://github.com/near/workspaces-js).

For **Go contracts**, unit tests are run with the `near-go` CLI:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
near-go test project
```

This runs unit tests using the `MockSystem` environment to simulate the NEAR blockchain locally — no sandbox required. For full integration tests that deploy to a sandbox, Go contracts use the Rust `workspaces-rs` framework. See the [Go Integration Testing](#go-integration-testing) section below.

<Note>
  **Sandbox Testing**

  NEAR Sandbox allows you to write tests once, and run them either on `testnet` or a local `Sandbox`. By **default**, Sandbox will start a **sandbox** and run your tests **locally**. Lets dive into the features of our framework and see how they can help you.
</Note>

***

## Create Accounts

### Account

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="16" end="31" />
  </Tab>
</Tabs>

<hr class="subsection" />

### Dev Account

<Tabs>
  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="49" end="69" />
  </Tab>
</Tabs>

### Subaccount

<Tabs>
  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="75" end="95" />
  </Tab>
</Tabs>

### Using Secret Key

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="40" end="57" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="101" end="128" />
  </Tab>
</Tabs>

### Using Credentials From File

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="66" end="89" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="134" end="161" />
  </Tab>
</Tabs>

***

## WASM Files

### Compile Contract Code

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="98" end="102" />

    <Tip>
      You don't need to assert compiling process everytime. You can use `?` operator to get the result as `Vec<u8>` without dealing with `Result<Vec<u8>>, Error>` type. That way you can directly use this vector to deploy the wasm file into account. Your test will still fail if compiling process fails.

      ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
      let contract_wasm_path = cargo_near_build::build_with_cli(Default::default())?;
      ```
    </Tip>
  </Tab>

  <Tab title="🌐 JavaScript">
    If you want to compile a contract each time running tests, you can put following scripts into `package.json` file. In the code you can access path to compiled file using `process.argv[2]`.

    `package.json` file:

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    "scripts": {
      "build": "near-sdk-js build src/contract.ts build/hello_near.wasm",
      "test": "$npm_execpath run build && ava -- ./build/hello_near.wasm"
    },
    ```

    `main.ava.js` file:

    ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const pathToWasm = process.argv[2];
    await contract.deploy(pathToWasm);
    ```
  </Tab>
</Tabs>

### Loading From File

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="109" end="116" />

    <Tip>
      The same as in the case of compilation wasm from code, you don't need to assert reading file process everytime. You can use `expect` method to get the reading file result as `Vec<u8>` and provide error message as a parameter. Your test will still fail if compiling process fails.

      ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
      let contract_wasm = std::fs::read(artifact_path)
          .expect(format!("Could not read WASM file from {}", artifact_path).as_str());
      ```
    </Tip>
  </Tab>

  <Tab title="🌐 JavaScript">
    If you want to use pre-compiled a contract, you can put following scripts into `package.json` file. In the code you can access path to pre-compiled file using `process.argv[2]`.

    `package.json` file:

    ```json theme={"theme":{"light":"github-light","dark":"github-dark"}}
    "scripts": {
      "build": "near-sdk-js build src/contract.ts build/hello_near.wasm",
      "test": "ava -- ./build/hello_near.wasm"
    },
    ```

    `main.ava.js` file:

    ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const pathToWasm = process.argv[2];
    await contract.deploy(pathToWasm);
    ```
  </Tab>
</Tabs>

***

## Deploy Contracts

### Dev Deploy

<Tabs>
  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="167" end="188" />
  </Tab>
</Tabs>

### Deploy To Account

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="123" end="159" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="17" end="23" />
  </Tab>
</Tabs>

***

## Logs

Show contract's logs.

<Tabs>
  <Tab title="🦀 Rust">
    You can use `println` or `dbg!` when you want to see information from your code.

    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="24" end="31" />

    In Rust, the output from your code is captured by default and not displayed in the terminal. In order to see the output, you have to use the `--nocapture` flag

    eg. `cargo test -- --nocapture`

    If you want to access the contracts logs, you can find them in the `tx_outcome.logs()` Vec.

    ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
    let tx_outcome = contract
            .call_function("set_greeting", json!({"greeting": "Hello World!"}))
            .transaction()
            .gas(Gas::from_tgas(100))
            .with_signer(contract.account_id().clone(), signer.clone())
            .send_to(&sandbox_network)
            .await?;
        assert!(tx_outcome.is_success());

        dbg!(tx_outcome.logs());
        // [tests/test_basics.rs:29:5] tx_outcome.logs() = [
        //     "Saving greeting: Hello World!",
        // ]
    ```
  </Tab>

  <Tab title="🌐 JavaScript">
    Use `console.log` method when you want to see debug information from your code.

    ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const balance = await account.balance();

    console.log('balance: ', balance);
    // balance:  {
    //   total: <BN: 52b7d2dcc80cd2e4000000>,
    //   stateStaked: <BN: 62a992e53a0af00000>,
    //   staked: <BN: 0>,
    //   available: <BN: 52b77033352798d9100000>
    // }
    ```
  </Tab>
</Tabs>

***

## Account Balance

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="168" end="199" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="194" end="205" />
  </Tab>
</Tabs>

***

## Transactions

### Call

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="208" end="257" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="42" end="43" />
  </Tab>
</Tabs>

### View

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="266" end="323" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="36" end="37" />
  </Tab>
</Tabs>

***

## Patch State on the Fly

In Sandbox-mode, you can add or modify any contract state, contract code, account or access key with `patchState`.

You can alter contract code, accounts, and access keys using normal transactions via the `DeployContract`, `CreateAccount`, and `AddKey` [actions](https://nomicon.io/RuntimeSpec/Actions#addkeyaction). But this limits you to altering your own account or sub-account. `patchState` allows you to perform these operations on any account.

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="332" end="384" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="211" end="222" />

    To see a complete example of how to do this, see the [patch-state test](https://github.com/near/workspaces-js/blob/main/__tests__/02.patch-state.ava.ts).
  </Tab>
</Tabs>

<Note>
  As an alternative to `patchState`, you can stop the node, dump state at genesis, edit the genesis, and restart the node.
  This approach is more complex to do and also cannot be performed without restarting the node.
</Note>

***

## Time Traveling

`sandbox` offers support for forwarding the state of the blockchain to the future. This means contracts which require time sensitive data do not need to sit and wait the same amount of time for blocks on the sandbox to be produced. We can simply just call `sandbox.fast_forward` to get us further in time:

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="393" end="444" />

    *[See the full example on Github](https://github.com/near/workspaces-rs/blob/main/examples/src/fast_forward.rs).*
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="228" end="248" />
  </Tab>
</Tabs>

***

## Using Testnet

NEAR Sandbox is set up so that you can write tests once and run them against a local Sandbox node (the default behavior) or against [NEAR TestNet](../../protocol/network/networks). Some reasons this might be helpful:

* Gives higher confidence that your contracts work as expected
* You can test against deployed testnet contracts
* If something seems off in Sandbox mode, you can compare it to testnet

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="458" end="499" />

    <Tip>
      If you can create a new account on each iteration as well.
    </Tip>
  </Tab>

  <Tab title="🌐 JavaScript">
    You can switch to testnet mode in three ways:

    <Accordion title="1. Setting the `Worker` network to `testnet`">
      When creating Worker set network to `testnet` and pass your master account (an account for which you have the private key):

      ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
      const worker = await Worker.init({
        network: 'testnet',
        testnetMasterAccountId: '<yourAccountName>',
        initialBalance: NEAR.parse("<X> N").toString(),
      })
      ```
    </Accordion>

    <Accordion title="2. Setting environment variables">
      Set the `NEAR_WORKSPACES_NETWORK` and `TESTNET_MASTER_ACCOUNT_ID` (an account for which you have the private key) environment variables when running your tests:

      ```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
      NEAR_WORKSPACES_NETWORK=testnet TESTNET_MASTER_ACCOUNT_ID=<your master account Id> node test.js
      ```

      If you set this environment variables and pass `{network: 'testnet', testnetMasterAccountId: <masterAccountId>}` to `Worker.init`, the config object takes precedence.
    </Accordion>

    <Accordion title="3. Config file">
      If you are using AVA, you can use a custom config file. Other test runners allow similar config files; adjust the following instructions for your situation.

      Create a file in the same directory as your `package.json` called `ava.testnet.config.cjs` with the following contents:

      ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
      module.exports = {
      ...require('near-workspaces/ava.testnet.config.cjs'),
      ...require('./ava.config.cjs'),
      };
      module.exports.environmentVariables = {
          TESTNET_MASTER_ACCOUNT_ID: '<masterAccountId>',
      };
      ```

      Where the master account is an account for which you have the private key.

      The [near-workspaces/ava.testnet.config.cjs](https://github.com/near/workspaces-js/blob/main/ava.testnet.config.cjs) import sets the `NEAR_WORKSPACES_NETWORK` environment variable for you. A benefit of this approach is that you can then easily ignore files that should only run in Sandbox mode.

      Now you'll also want to add a `test:testnet` script to your `package.json`'s `scripts` section:

      ```diff theme={"theme":{"light":"github-light","dark":"github-dark"}}
      "scripts": {
        "test": "ava",
      +  "test:testnet": "ava --config ./ava.testnet.config.cjs"
      }
      ```
    </Accordion>

    To use the accounts, you will need to create the `.near-credentials/workspaces/testnet` directory and add files for your master account, for example:

    ```js theme={"theme":{"light":"github-light","dark":"github-dark"}}
    // .near-credentials/workspaces/testnet/<your-account>.testnet.json
    {"account_id":"<your-account>.testnet","public_key":"ed25519:...","private_key":"ed25519:..."}
    ```

    Example:

    <Github fname="main.ava.js" language="js" url="https://github.com/near-examples/near-workspaces-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="252" end="263" />
  </Tab>
</Tabs>

***

## Spooning Contracts

[Spooning a blockchain](https://coinmarketcap.com/alexandria/glossary/spoon-blockchain) is copying the data from one network into a different network. NEAR Sandbox makes it easy to copy data from Mainnet or Testnet contracts into your local Sandbox environment:

<Tabs>
  <Tab title="🦀 Rust">
    Specify the contract name from `testnet` you want to be pulling, and a specific block ID referencing back to a specific time. (Just in case the contract you're referencing has been changed or updated)

    Create a function called `pull_contract` which will pull the contract's `.wasm` file from the chain and deploy it onto your local sandbox. You'll have to re-initialize it with all the data to run tests. This is because the contract's data is too big for the RPC service to pull down. (limits are set to 50Mb)

    <Github fname="basics.rs" language="rust" url="https://github.com/near-examples/near-workspaces-examples/blob/workspaces-migration/contract-rs/tests/basics.rs" start="507" end="537" />
  </Tab>

  <Tab title="🌐 JavaScript">
    ```ts theme={"theme":{"light":"github-light","dark":"github-dark"}}
    const refFinance = await root.importContract({
      mainnetContract: 'v2.ref-finance.near',
      blockId: 50_000_000,
      withData: true,
    });
    ```

    This would copy the Wasm bytes and contract state from [v2.ref-finance.near](https://nearblocks.io/address/v2.ref-finance.near) to your local blockchain as it existed at block `50_000_000`. This makes use of Sandbox's special [patch state](#patch-state-on-the-fly) feature to keep the contract name the same, even though the top level account might not exist locally (note that this means it only works in Sandbox testing mode). You can then interact with the contract in a deterministic way the same way you interact with all other accounts created with near-workspaces.

    <Note>
      `withData` will only work out-of-the-box if the contract's data is 50kB or less. This is due to the default configuration of RPC servers; see [the "Heads Up" note here](/api/rpc/contracts#view-contract-state).
    </Note>

    See a [TypeScript example of spooning](https://github.com/near/workspaces-js/blob/main/__tests__/05.spoon-contract-to-sandbox.ava.ts) contracts.
  </Tab>
</Tabs>

***

## Snippets

### Snippet I: Testing Hello NEAR

Lets take a look at the test of our [Quickstart Project](../quickstart) [👋 Hello NEAR](https://github.com/near-examples/hello-near-examples), where we deploy the contract on an account and test it correctly retrieves and sets the greeting.

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="test_basics.rs" url="https://github.com/near-examples/hello-near-examples/blob/main/contract-rs/tests/test_basics.rs" start="1" end="32" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.ts" url="https://github.com/near-examples/hello-near-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="11" end="45" />
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="test_greeting.rs" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/greeting/integration-tests/tests/test_greeting.rs" start="1" end="77" />
  </Tab>
</Tabs>

<hr class="subsection" />

### Snippet II: Testing Donations

In most cases we will want to test complex methods involving multiple users and money transfers. A perfect example for this is our [Donation Example](https://github.com/near-examples/donation-examples), which enables users to `donate` money to a beneficiary. Lets see its integration tests

<Tabs>
  <Tab title="🦀 Rust">
    <Github fname="workspaces.rs" url="https://github.com/near-examples/donation-examples/blob/main/contract-rs/tests/workspaces.rs" start="1" end="106" />
  </Tab>

  <Tab title="🌐 JavaScript">
    <Github fname="main.ava.ts" url="https://github.com/near-examples/donation-examples/blob/main/contract-ts/sandbox-test/main.ava.js" start="51" end="75" />
  </Tab>

  <Tab title="🐹 GO">
    <Github fname="test_donation.rs" url="https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/donation/integration-tests/tests/test_donation.rs" start="1" end="81" />
  </Tab>
</Tabs>

***

## Go Integration Testing

Go contracts use the Rust `workspaces-rs` framework for integration tests. The workflow is:

1. Build your contract to WASM with `near-go build`
2. Write integration tests in a separate Rust project using `workspaces-rs`
3. Run with `cargo test`

<Note>
  **Unit tests vs Integration tests**

  `near-go test project` runs **unit tests** using the `MockSystem` environment locally. For full integration tests that deploy to a sandbox, use the `workspaces-rs` Rust crate as described below.
</Note>

### Project Structure

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
my-contract/
├── main.go              # your Go contract
├── go.mod
├── go.sum
└── integration-tests/   # Standalone Rust integration test project
    ├── Cargo.toml
    └── tests/
        └── test_my_contract.rs
```

### Running Tests

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
# Step 1: Build the Go contract to WASM (from the contract root)
near-go build

# Step 2: Run integration tests
cargo test --manifest-path integration-tests/Cargo.toml
```

### Writing Integration Tests

Integration tests follow the `workspaces-rs` pattern. The compiled `main.wasm` sits one directory above `integration-tests/`, so tests load it with `std::fs::read("../main.wasm")`.

<Warning>
  **Double-encoded return values**

  `near-sdk-go` wraps every return value in an extra JSON string encoding. When reading a view result, always deserialize in **two steps**: first parse the outer `String`, then parse the inner type.

  ```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
  // ✅ Correct two-step deserialization
  let raw: String = contract.view("get_greeting").args_json(json!({})).await?.json()?;
  let greeting: String = serde_json::from_str(&raw)?;

  // ❌ Will fail – skips the outer wrapper
  let greeting: String = contract.view("get_greeting").args_json(json!({})).await?.json()?;
  ```
</Warning>

```rust theme={"theme":{"light":"github-light","dark":"github-dark"}}
// integration-tests/tests/test_greeting.rs
use serde_json::json;

#[tokio::test]
async fn test_greeting_init() -> anyhow::Result<()> {
    let sandbox = near_workspaces::sandbox().await?;
    let wasm = std::fs::read("../main.wasm")?;
    let contract = sandbox.dev_deploy(&wasm).await?;

    contract
        .call("init")
        .args_json(json!({}))
        .transact()
        .await?
        .into_result()?;

    // Two-step deserialization: outer String wrapper → inner type
    let raw: String = contract.view("get_greeting").args_json(json!({})).await?.json()?;
    let greeting: String = serde_json::from_str(&raw)?;
    assert_eq!(greeting, "Hello");
    Ok(())
}

#[tokio::test]
async fn test_set_greeting() -> anyhow::Result<()> {
    let sandbox = near_workspaces::sandbox().await?;
    let wasm = std::fs::read("../main.wasm")?;
    let contract = sandbox.dev_deploy(&wasm).await?;

    contract.call("init").args_json(json!({})).transact().await?.into_result()?;

    let caller = sandbox.dev_create_account().await?;
    caller
        .call(contract.id(), "set_greeting")
        .args_json(json!({ "greeting": "Howdy" }))
        .transact()
        .await?
        .into_result()?;

    let raw: String = contract.view("get_greeting").args_json(json!({})).await?.json()?;
    let greeting: String = serde_json::from_str(&raw)?;
    assert_eq!(greeting, "Howdy");
    Ok(())
}
```

```toml theme={"theme":{"light":"github-light","dark":"github-dark"}}
# integration-tests/Cargo.toml
[package]
name = "greeting-integration-tests"
version = "0.1.0"
edition = "2021"

[dev-dependencies]
near-workspaces = "0.22.0"
tokio = { version = "1.41.1", features = ["full"] }
anyhow = "1.0.93"
serde_json = "1.0.133"
serde = { version = "1.0.215", features = ["derive"] }
```

<Tip>
  You can also test your Go contract on NEAR testnet by deploying it first with `near deploy` and calling methods via the `near` CLI.

  [See full example on GitHub](https://github.com/Emir-Asanov/near-go-examples/blob/example-release-1/greeting/integration-tests/tests/test_greeting.rs)
</Tip>

***

## Additional Resources

### Advanced Examples

* [Rust](https://github.com/near/near-sandbox-rs/tree/main/examples)
* [JavaScript](https://github.com/near/near-workspaces-js/tree/main/__tests__)

### Test Driven Design Using Workspaces and AVA

The video below walks through how to apply TDD with Workspaces and AVA for a simple contract:

<iframe width="560" height="315" src="https://www.youtube-nocookie.com/embed/LCu03IYwu1I" title="TDD Using Workspaces" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen />
