# Local testing using a Mock contract
Source: https://docs.chain.link/vrf/v2/subscription/examples/test-locally

> For the complete documentation index, see [llms.txt](/llms.txt).

> **TIP: VRF V2.5 Subscription Mock Tutorial**
>
> Refer to the [VRF V2.5 version of this subscription mock tutorial](/vrf/v2-5/subscription/test-locally) to learn how
> to test locally with VRF V2.5. To compare V2.5 and V2, refer to the [migration guide](/vrf/v2-5/migration-from-v2).This guide explains how to test Chainlink VRF v2 on a [Remix IDE](https://remix-ide.readthedocs.io/en/latest/run.html#environment) sandbox blockchain environment. **Note**: You can reuse the same logic on another development environment, such as Hardhat or Truffle. For example, read the Hardhat Starter Kit [RandomNumberConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberConsumer.spec.js).> **CAUTION: Test on public testnets thoroughly**
>
> Even though local testing has several benefits, testing with a VRF mock covers the bare minimum of use cases. Make
> sure to test your consumer contract thoroughly on public testnets.## Benefits of local testing## Testing logicComplete the following tasks to test your VRF v2 consumer locally:1) Deploy the [VRFCoordinatorV2Mock](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol). This contract is a mock of the [VRFCoordinatorV2](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/VRFCoordinatorV2.sol) contract.
2) Call the VRFCoordinatorV2Mock [createSubscription function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L194) to create a new subscription.
3) Call the VRFCoordinatorV2Mock [fundSubscription function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L156) to fund your newly created subscription. **Note**: You can fund with an arbitrary amount.
4) Deploy your VRF consumer contract.
5) Call the VRFCoordinatorV2Mock [addConsumer function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L230) to add your consumer contract to your subscription.
6) Request random words from your consumer contract.
7) Call the VRFCoordinatorV2Mock [fulfillRandomWords function](https://github.com/smartcontractkit/chainlink/blob/contracts-v1.3.0/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol#L108) to fulfill your consumer contract request.## Testing### Open the contracts on RemixIDEOpen *VRFCoordinatorV2Mock* and compile in Remix:```sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "@chainlink/contracts/src/v0.8/vrf/mocks/VRFCoordinatorV2Mock.sol";
```Open *VRFv2Consumer* and compile in Remix:```sol
// SPDX-License-Identifier: MIT
// An example of a consumer contract that relies on a subscription for funding.
pragma solidity ^0.8.7;

import {VRFConsumerBaseV2} from "@chainlink/contracts/src/v0.8/vrf/VRFConsumerBaseV2.sol";
import {VRFCoordinatorV2Interface} from "@chainlink/contracts/src/v0.8/vrf/interfaces/VRFCoordinatorV2Interface.sol";

/**
 * THIS IS AN EXAMPLE CONTRACT THAT USES HARDCODED VALUES FOR CLARITY.
 * THIS IS AN EXAMPLE CONTRACT THAT USES UN-AUDITED CODE.
 * DO NOT USE THIS CODE IN PRODUCTION.
 */

/**
 * @title The RandomNumberConsumerV2 contract
 * @notice A contract that gets random values from Chainlink VRF V2
 */
contract RandomNumberConsumerV2 is VRFConsumerBaseV2 {
  VRFCoordinatorV2Interface immutable COORDINATOR;

  // Your subscription ID.
  uint64 immutable s_subscriptionId;

  // The gas lane to use, which specifies the maximum gas price to bump to.
  // For a list of available gas lanes on each network,
  // see https://docs.chain.link/docs/vrf-contracts/#configurations
  bytes32 immutable s_keyHash;

  // Depends on the number of requested values that you want sent to the
  // fulfillRandomWords() function. Storing each word costs about 20,000 gas,
  // so 100,000 is a safe default for this example contract. Test and adjust
  // this limit based on the network that you select, the size of the request,
  // and the processing of the callback request in the fulfillRandomWords()
  // function.
  uint32 constant CALLBACK_GAS_LIMIT = 100_000;

  // The default is 3, but you can set this higher.
  uint16 constant REQUEST_CONFIRMATIONS = 3;

  // For this example, retrieve 2 random values in one request.
  // Cannot exceed VRFCoordinatorV2.MAX_NUM_WORDS.
  uint32 constant NUM_WORDS = 2;

  uint256[] public s_randomWords;
  uint256 public s_requestId;
  address s_owner;

  event ReturnedRandomness(uint256[] randomWords);

  /**
   * @notice Constructor inherits VRFConsumerBaseV2
   *
   * @param subscriptionId - the subscription ID that this contract uses for funding requests
   * @param vrfCoordinator - coordinator, check https://docs.chain.link/docs/vrf-contracts/#configurations
   * @param keyHash - the gas lane to use, which specifies the maximum gas price to bump to
   */
  constructor(
    uint64 subscriptionId,
    address vrfCoordinator,
    bytes32 keyHash
  ) VRFConsumerBaseV2(vrfCoordinator) {
    COORDINATOR = VRFCoordinatorV2Interface(vrfCoordinator);
    s_keyHash = keyHash;
    s_owner = msg.sender;
    s_subscriptionId = subscriptionId;
  }

  /**
   * @notice Requests randomness
   * Assumes the subscription is funded sufficiently; "Words" refers to unit of data in Computer Science
   */
  function requestRandomWords() external onlyOwner {
    // Will revert if subscription is not set and funded.
    s_requestId =
      COORDINATOR.requestRandomWords(s_keyHash, s_subscriptionId, REQUEST_CONFIRMATIONS, CALLBACK_GAS_LIMIT, NUM_WORDS);
  }

  /**
   * @notice Callback function used by VRF Coordinator
   *
   * @param  - id of the request
   * @param randomWords - array of random results from VRF Coordinator
   */
  function fulfillRandomWords(
    uint256,
    /* requestId */
    uint256[] memory randomWords
  ) internal override {
    s_randomWords = randomWords;
    emit ReturnedRandomness(randomWords);
  }

  modifier onlyOwner() {
    require(msg.sender == s_owner);
    _;
  }
}
```Your RemixIDE file explorer should display *VRFCoordinatorV2Mock.sol* and *VRFv2Consumer.sol*:![Image](/images/vrf/mock/v2-subscription-remix-fileexplorer.jpg)### Deploy VRFCoordinatorV2Mock1) Open *VRFCoordinatorV2Mock.sol*.

2) Under *DEPLOY & RUN TRANSACTIONS*, select *VRFCoordinatorV2Mock*.

   ![Image](/images/vrf/mock/v2-deploymock.jpg)

3) Under *DEPLOY*, fill in the `_BASEFEE` and `_GASPRICELINK`. These variables are used in the *VRFCoordinatorV2Mock* contract to represent the base fee and the gas price (in LINK tokens) for the VRF requests. You can set: `_BASEFEE=100000000000000000` and `_GASPRICELINK=1000000000`.

4) Click on *transact* to deploy the *VRFCoordinatorV2Mock* contract.

5) Once deployed, you should see the *VRFCoordinatorV2Mock* contract under *Deployed Contracts*.

   ![Image](/images/vrf/mock/v2-deployedmock.jpg)

6) Note the address of the deployed contract.### Create and fund a subscription1) Click on `createSubscription` to create a new subscription.

2) In the RemixIDE console, read your transaction decoded output to find the subscription ID. In this example, the subscription ID is *1*.

   ![Image](/images/vrf/mock/v2-mocksubscription.jpg)

3) Click on `fundSubscription` to fund your subscription. In this example, you can set the `_subid` to `1` (which is your newly created subscription ID) and the `_amount` to `1000000000000000000`.### Deploy the VRF consumer contract1) In the file explorer, open *VRFv2Consumer.sol*.

2) Under *DEPLOY & RUN TRANSACTIONS*, select *RandomNumberConsumerV2*.

   ![Image](/images/vrf/mock/v2-deployconsumer.jpg)

3) Under *DEPLOY*, fill in `SUBSCRIPTIONID` with your subscription ID, `vrfCoordinator` with the deployed *VRFCoordinatorV2Mock* address and, *KEYHASH* with an arbitrary `bytes32` (In this example, you can set the *KEYHASH* to `0xd89b2bf150e3b9e13446986e571fb9cab24b13cea0a43ea20a6049a85cc807cc`).

4) Click on *transact* to deploy the *RandomNumberConsumerV2* contract.

5) After the consumer contract is deployed, you should see the *RandomNumberConsumerV2* contract under *Deployed Contracts*.

   ![Image](/images/vrf/mock/v2-deployedconsumer.jpg)

6) Note the address of the deployed contract.### Add the consumer contract to your subscription1) Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2Mock* contract.

2) Click on *addConsumer* and fill in the `_subid` with your subscription ID and `_consumer` with your deployed consumer contract address.

   ![Image](/images/vrf/mock/v2-addconsumer.jpg)

3) Click on *transact*.### Request random words1) Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberConsumerV2* contract.

2) Click on `requestRandomWords`.

   ![Image](/images/vrf/mock/v2-requestrandomwords.jpg)

3) In the RemixIDE console, read your transaction logs to find the VRF request ID. In this example, the request ID is *1*.

   ![Image](/images/vrf/mock/v2-requestrandomwordslogs.jpg)

4) Note your request ID.### Fulfill the VRF requestBecause you are testing on a local blockchain environment, you must fulfill the VRF request yourself.1) Under *Deployed Contracts*, open the functions list of your deployed *VRFCoordinatorV2Mock* contract.

2) Click `fulfillRandomWords` and fill in `_requestId` with your VRF request ID and `_consumer` with your consumer contract address.

   ![Image](/images/vrf/mock/v2-fulfillrandomwords.jpg)

3) Click on `transact`.### Check the results1) Under *Deployed Contracts*, open the functions list of your deployed *RandomNumberConsumerV2* contract.

2) Click on `s_requestId` to display the last request ID. In this example, the output is *1*.

   ![Image](/images/vrf/mock/v2-deployedconsumerrequestid.jpg)

3) Each time you make a VRF request, your consumer contract requests two random words. After the request is fulfilled, the two random words are stored in the `s_randomWords` array. You can check the stored random words by reading the two first indexes of the `s_randomWords` array. To do so, click on the *s\_randomWords* function and:
   1. Fill in the index with *0* then click on *call* to read the first random word.

      ![Image](/images/vrf/mock/v2-firstrandomword.jpg)

   2. Fill in the index with *1* then click on *call* to read the second random word.

      ![Image](/images/vrf/mock/v2-secondrandomword.jpg)## Next stepsThis guide demonstrated how to test a VRF v2 consumer contract on your local blockchain. We made the guide on RemixIDE for learning purposes, but you can reuse the same [testing logic](#testing-logic) on another development environment, such as Truffle or Hardhat. For example, read the Hardhat Starter Kit [RandomNumberConsumer unit tests](https://github.com/smartcontractkit/hardhat-starter-kit/blob/main/test/unit/RandomNumberConsumer.spec.js).