> ## Documentation Index
> Fetch the complete documentation index at: https://docs.near.org/llms.txt
> Use this file to discover all available pages before exploring further.

# Unit Testing

> Learn how to write and run unit tests for NEAR smart contracts to test individual methods and functions in isolation.

export const Github = ({url, start, end, fname, language, 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 fileName = fname ?? sourceUrl.split('/').pop();
  return <div className="my-5">
      {code === null ? <div>Loading...</div> : <CodeBlock language={language} filename={fileName} lines>
          {code}
        </CodeBlock>}
      {withSourceLink && <div className="flex justify-end" style={{
    marginTop: "-1rem"
  }}>
          <a href={sourceUrl} target="_blank" rel="noreferrer noopener" className="text-[0.6875rem] font-medium text-[#656d76] no-underline hover:text-[#1f2328] dark:text-[#8b949e] dark:hover:text-[#e6edf3]">
            See code on GitHub
          </a>
        </div>}
    </div>;
};

Smart contracts need both unit and integration tests:

1. **Unit tests** exercise methods individually. They are written in Rust alongside the contract and run locally.
2. **Integration tests** deploy the compiled contract to a local Sandbox or testnet and exercise it through transactions.

Use unit tests for contract logic and state changes. Use [integration tests](/smart-contracts/testing/integration-test) for behavior that depends on the runtime, including cross-contract calls, gas, attached deposits, and multiple accounts.

We recommend using both types of tests and testing on testnet before deploying a contract to mainnet.

***

Unit tests allow you to test the contract methods individually. They are suitable to check the storage is updated correctly, and that methods return their expected values. They are written in Rust alongside the contract's code and execute locally.

To run the unit tests, simply navigate to the contract's folder and run `cargo test`:

```bash theme={"theme":{"light":"github-light","dark":"github-dark"}}
cargo test
```

<Tip>
  `cargo test` runs both unit and [integration](/smart-contracts/testing/integration-test) tests present in the project.
</Tip>

***

## Snippet I: Testing a Counter

The tests in the [Counter Example](https://github.com/near-examples/counters) rely on basic functions to check that the `increment`, `decrement`, and `reset` methods work properly.

<Github fname="lib.rs" url="https://github.com/near-examples/counters/blob/main/contract-rs/src/lib.rs" start="47" end="84" />

<Github fname="Cargo.toml" url="https://github.com/near-examples/counters/blob/main/contract-rs/Cargo.toml" start="18" end="19" />

***

## Snippet II: Modifying the Context

While doing unit testing you can modify the [Environment variables](../anatomy/environment) through the `VMContextBuilder`. This will enable you to, for example, simulate calls from different users, with specific attached deposit and GAS. Here we present a snippet on how we test the `donate` method from our [Donation Example](https://github.com/near-examples/donation-examples) by manipulating the `predecessor` and `attached_deposit`.

<Github fname="lib.rs" url="https://github.com/near-examples/donation-examples/blob/main/contract-rs/src/lib.rs" start="58" end="105" />

<Github fname="Cargo.toml" url="https://github.com/near-examples/donation-examples/blob/main/contract-rs/Cargo.toml" start="18" end="19" />

***

## ⚠️ Limitations

Unit tests are useful to check for code integrity, and detect basic errors on isolated methods. However, since unit tests do not run on a blockchain, there are many things which they cannot detect. Unit tests are not suitable for:

* Testing [gas](../anatomy/environment) and [storage](../anatomy/storage) usage
* Testing [transfers](../anatomy/actions)
* Testing [cross-contract calls](../anatomy/crosscontract)
* Testing complex interactions, i.e. multiple users depositing money on the contract

For all these cases it is necessary to **complement** unit tests with [integration tests](/smart-contracts/testing/integration-test).
