---
page_title: Tests - Provider Mocking
description: >-
  Provide mocked data for providers and resources in your tests.
---

# Mocks

-> **Note**: Test mocking is available in Terraform v1.7.0 and later. This feature is in beta.

Terraform lets you mock providers, resources, and data sources for your tests. This allows you to test parts of your module without creating infrastructure or requiring credentials. In a Terraform test, a mocked provider or resource will generate fake data for all computed attributes that would normally be provided by the underlying provider APIs.

Mocking functionality can only be used with the [`terraform test` language](/terraform/language/tests). Readers of this documentation should be familiar with the testing syntax and language features.

In addition, the more advanced features of the mocking framework require knowledge about the following Terraform provider features:

- The difference between [attributes, nested attributes,](/terraform/plugin/framework/handling-data/attributes) and [blocks](https://developer.hashicorp.com/terraform/plugin/framework/handling-data/blocks).
- Definitions of [optional, required, and computed attributes](/terraform/plugin/framework/handling-data/attributes/string#configurability).


## Mock Providers

In Terraform tests, you can mock a provider with the `mock_provider` block. Mock providers return the same schema as the original provider and you can pass the mocked provider to your tests in place of the matching provider. All resources and data sources retrieved by a mock provider will set the relevant values from the configuration, and generate fake data for any computed attributes.

Mock providers can be used directly in place of traditional `provider` blocks and they share the same global namespace. During the execution of the `terraform test` command, Terraform does not distinguish between a real and a mocked provider.

The following example creates an AWS S3 bucket and then uses a mocked provider to test the configuration without requiring an AWS account.

```hcl
# main.tf

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

variable "bucket_name" {
  type = string
}

resource "aws_s3_bucket" "my_bucket" {
  bucket = var.bucket_name
}
```

```hcl
# bucket_name.tftest.hcl

mock_provider "aws" {}

run "sets_correct_name" {
  variables {
    bucket_name = "my-bucket-name"
  }

  assert {
    condition     = aws_s3_bucket.my_bucket.bucket == "my-bucket-name"
    error_message = "incorrect bucket name"
  }
}
```

From the perspective of a `plan` or `apply` operation executed in a Terraform test file, the mocked provider is creating actual resources with values that match the configuration. These resources are stored in the Terraform state files that `terraform test` creates and holds in memory during test executions.

You can use mocked providers and real providers simulating in a Terraform test. The following example defines two AWS providers, one real and one mocked. You must provide an alias to one of them, as they share the same global `aws` provider namespace. You can then use the `providers` attribute in test `run` blocks to customize which AWS provider to use for each `run` block. 

```hcl
# mocked_providers.tftest.hcl

provider "aws" {}

mock_provider "aws" {
  alias = "fake"
}

run "use_real_provider" {
  providers = {
    aws = aws
  }
}

run "use_mocked_provider" {
  providers = {
    aws = aws.fake
  }
}
```

### Generated data

A mocked provider will generate data for any computed attributes in referenced data sources or attributes. For example, the `arn` attribute is a unique identifier generated by AWS for most resources. A mocked `aws` provider will provide a value for this attribute in any resources it creates.

-> **Note**: Mocked providers do not have any information about the expected format of the computed attributes, so the generated data will rarely match any expected syntax that real providers would return for those attributes.

Mocked providers only generate data for computed attributes. All required resource attributes must be set when you use a mocked provider. If you do not provide a value for an optional computed attribute, Terraform will automatically generate one. The values that Terraform generates depends on the data type:

- Numbers will be 0.
- Booleans will be false.
- Strings will be a random 8 character alphanumeric string.
- Collections, including sets, lists, and maps, will be empty collections.
- Objects will contain all required sub-attributes generated using this same set of rules recursively.

An example of this is the `bucket` attribute in the `aws_s3_bucket` resource. A real AWS provider will generate a bucket name if one is not specified. A mocked AWS provider will do the same, and only generate a value if one is not already specified in the configuration.

### Mock Provider data

You can specify specific values for targeted resources and data sources. in a `mock_provider` block, you can write any number of `mock_resource` and `mock_data` blocks. Both the `mock_resource` and `mock_data` blocks accept a type argument that should match the resource or data source you want to provide values for. They also accept a `defaults` object attribute that you can use to specify the values that should be returned for specific attributes.

The following example demonstrates providing a set `arn` value for all AWS S3 bucket resources and data sources:

```hcl
mock_provider "aws" {
  mock_resource "aws_s3_bucket" {
    defaults = {
      arn = "arn:aws:s3:::name"
    }
  }

  mock_data "aws_s3_bucket" {
    defaults = {
      arn = "arn:aws:s3:::name"
    }
  }
}
```

In the above example, Terraform uses the supplied value for `arn` attributes in S3 buckets instead of generating a random string. Computed attributes not provided an explicit default will simply fall back to the generic data generation rules.

You can also share mock provider data between tests by writing dedicated mock data files and using the `source` attribute in the `mock_provider` block. Mock data files have `.tfmock.hcl` or `.tfmock.json` extension, and can contain `mock_resource` and `mock_data` blocks as if they were defined in the `mock_provider` block directly.

```hcl
# ./testing/aws/data.tfmock.hcl

mock_resource "aws_s3_bucket" {
  defaults = {
    arn = "arn:aws:s3:::name"
  }
}

mock_data "aws_s3_bucket" {
  defaults = {
    arn = "arn:aws:s3:::name"
  }
}
```

```hcl
mock_provider "aws" {
  source = "./testing/aws"
}
```

The above example defines `mock_resource` and `mock_data` blocks in a mock data file located at `./testing/aws`. You can load multiple test files and share the same mock provider data without copying the same definitions across multiple files.

You can combine the `source` attribute with directly nested `mock_resource` and `mock_data` blocks. If the source location and a directly nested block describe the same resource or data source then the directly nested block takes precedence.

## Overrides

In addition to mocking providers, you can use the following block types to override specific resources, data sources, and modules: 

- `override_resource`: Override the values of a resource. Terraform does not call the underlying provider.
- `override_data`: Override the values of a data source. Terraform does not call the underlying provider.
- `override_module`: Override the outputs of a module. Terraform does not create any resource in the module.

All three blocks can be placed at the root level of Terraform test files and in Terraform test file `run` blocks. In addition, the `override_resource` and `override_data` blocks can be nested in `mock_provider` blocks and in Terraform mock data files. 

Overrides can be used with both real and mocked providers and will provide the computed values instead of the underlying provider.

### Overrides Syntax

All override blocks contain a `target` attribute, which should specify the resource, data source, or module to override. The `override_module` blocks contain an `outputs` attribute, while the `override_resource` and `override_data` blocks contain a `values` attribute.

The `outputs` and `values` attributes are optional and if not specified, Terraform will generate values for them automatically.

The following example demonstrates the override blocks at various different scopes and levels. The main configuration calls the `./modules/s3_data` module to read a file from an S3 bucket, and then creates a `local_file` from the data returned from the module.

```hcl
# main.tf

terraform {
  required_providers {
    aws = {
      source = "hashicorp/aws"
    }
  }
}

module "credentials" {
  source = "./modules/s3_data"

  data_bucket_name = "my_company_bucket_name"
}

resource "local_file" "credentials_json" {
  filename = "credentials.json"
  content  = jsonencode(module.credentials.data)
}
```

```hcl
# ./modules/s3_data/main.tf

variable "data_bucket_name" {
  type = string
}

data "aws_s3_object" "data_bucket" {
  bucket = var.data_bucket_name
  key    = "credentials.json"
}

output "data" {
  value = jsondecode(data.aws_s3_object.data_bucket.body)
}
```

Firstly, you can override the `aws_s3_bucket_object` in the module directly in a mock provider. The following example defines an `override_data` block in the `mock_provider` block. In this case, Terraform will only override the target data source if the mock provider creates it.

```hcl
# main.tftest.hcl

mock_provider "aws" {
  override_data {
    target = module.credentials.data.aws_s3_object.data_bucket
    values = {
      body = "{\"username\":\"username\",\"password\":\"password\"}"
    }
  }
}

run "test" {
  assert {
    condition     = jsondecode(local_file.credentials_json.content).username == "username"
    error_message = "incorrect username"
  }
}
```

Alternatively, you could also override the same `aws_s3_bucket_object` in the test file itself, or in a `run` block. In this case, the underlying provider doesn't matter since Terraform overrides the data source at the target address regardless of the provider. The following example still mocks the provider so that Terraform can run the test without AWS credentials. Override blocks can override resources provided by real providers.

```hcl
# main.tftest.hcl

mock_provider "aws" {}

override_data {
  target = module.credentials.data.aws_s3_object.data_bucket
  values = {
    body = "{\"username\":\"username\",\"password\":\"password\"}"
  }
}

run "test_file_override" {
  assert {
    condition     = jsondecode(local_file.credentials_json.content).username == "username"
    error_message = "incorrect username"
  }
}

run "test_run_override" {
  # The value in this local override block takes precedence over the
  # alternate defined in the file.
  override_data {
    target = module.credentials.data.aws_s3_object.data_bucket
    values = {
      body = "{\"username\":\"a_different_username\",\"password\":\"password\"}"
    }
  }

  assert {
    condition     = jsondecode(local_file.credentials_json.content).username == "a_different_username"
    error_message = "incorrect username"
  }
}
```

In the above example, the override block defined at the file level is used in the first `run` block. Then in the second `run` block, the alternative local override takes precedence over the file level override.

Finally, you can override the entire module with the `override_module` block. In the following example, Terraform overrides the entire module instead of specific resources in the module. 

```hcl
# main.tftest.hcl
mock_provider "aws" {}

override_module {
  target = module.credentials
  outputs = {
    data = { username = "username", password = "password" }
  }
}

run "test" {
  assert {
    condition     = jsondecode(local_file.credentials_json.content).username == "username"
    error_message = "incorrect username"
  }
}
```

In this case, the override block specifies `outputs` instead of `values` and the output value is specified as HCL instead of as a string as the real module is passing the data through the `jsondecode` function. As with `override_data` blocks, you can also specify the `override_module` block in the `run` block and the same precedence rules apply.

## Repeated blocks and nested attributes

Some resources and data sources specify repeated nested attributes as computed directly, while repeated blocks in the resource may also contain computed attributes. For repeated blocks and nested attributes, you cannot specify values for specific instances in the collection. Instead, you must provide a single set of values that apply for all instances in the collection.

For example, the `aws_dynamodb_table` resource contains a root-level computed `arn` attribute as well as a set-repeated block called `replica` which also contains a computed `arn` attribute. The following is an example of a simple instance of an `aws_dynamodb_table`.

```hcl
# main.tf

resource "aws_dynamodb_table" "my_table" {
  name     = "my_table"
  hash_key = "key"

  attribute {
    name = "key"
    type = "S"
  }

  replica {
    region_name = "eu-west-2"
  }

  replica {
    region_name = "us-east-1"
  }
}
```

Normally, the AWS provider would return ARN values for the DynamoDB table and both of the specified replicas. While a `mock_resource` block can mimic this behavior, it cannot differentiate between the multiple `replica` blocks in the resource:

```hcl
mock_resource "aws_dynamodb_table" {
  defaults = {
    arn = "aws:dynamodb:::my_table"
    replica = {
      arn = "aws:dynamodb:::my_replica"
    }
  }
}
```

In this case, the `mock_resource` provides a specific value for the ARN of the DynamoDB table, but the ARN values returned for the replica tables are shared between all instances.