From 2d5f51edd48cf620c39420927e643e253ec01cd1 Mon Sep 17 00:00:00 2001 From: Samsondeen Dare Date: Mon, 23 Feb 2026 14:11:10 +0100 Subject: [PATCH] add test for mock_resource --- .../command/testdata/test/mocking/main.tf | 11 +- .../mocking/tests/nested_mocked.tftest.hcl | 42 ++++- internal/command/testing/test_provider.go | 151 ++++++++++-------- 3 files changed, 133 insertions(+), 71 deletions(-) diff --git a/internal/command/testdata/test/mocking/main.tf b/internal/command/testdata/test/mocking/main.tf index 49506e06c3..9d0180ca1b 100644 --- a/internal/command/testdata/test/mocking/main.tf +++ b/internal/command/testdata/test/mocking/main.tf @@ -24,12 +24,17 @@ variable "child_instances" { resource "test_resource" "primary" { provider = test.primary - count = var.instances + count = var.instances +} + +resource "test_complex_resource" "primary" { + provider = test.primary + count = var.instances } resource "test_resource" "secondary" { provider = test.secondary - count = var.instances + count = var.instances } module "child" { @@ -38,7 +43,7 @@ module "child" { source = "./child" providers = { - test.primary = test.primary + test.primary = test.primary test.secondary = test.secondary } diff --git a/internal/command/testdata/test/mocking/tests/nested_mocked.tftest.hcl b/internal/command/testdata/test/mocking/tests/nested_mocked.tftest.hcl index 8c5925ac62..28cb1d9be7 100644 --- a/internal/command/testdata/test/mocking/tests/nested_mocked.tftest.hcl +++ b/internal/command/testdata/test/mocking/tests/nested_mocked.tftest.hcl @@ -1,15 +1,29 @@ mock_provider "test" { alias = "primary" - mock_resource "test_resource" { + mock_resource "test_complex_resource" { defaults = { id = "aaaa" list_value = [{name = "first"}, {name = "second"}] nested_list_value = [{name = "first"}, {name = "second"}] set_value = [{name = "first"}, {name = "second"}] nested_set_value = [{name = "first"}, {name = "second"}] - map_value = [{name = "first"}, {name = "second"}] - nested_map_value = [{name = "first"}, {name = "second"}] + map_value = { + "key1": { + name = "first" + }, + "key2": { + name = "third" + } + } + nested_map_value = { + "key1": { + name = "first" + }, + "key2": { + name = "third" + } + } } } } @@ -23,7 +37,27 @@ variables { run "test" { assert { - condition = test_resource.primary[0].id == "aaaa" + condition = test_complex_resource.primary[0].id == "aaaa" + error_message = "did not apply mocks" + } + + assert { + condition = test_complex_resource.primary[0].list_value[0].name == "first" + error_message = "did not apply mocks" + } + + assert { + condition = test_complex_resource.primary[0].nested_list_value[0].name == "first" + error_message = "did not apply mocks" + } + + assert { + condition = test_complex_resource.primary[0].map_value["key1"].name == "first" + error_message = "did not apply mocks" + } + + assert { + condition = test_complex_resource.primary[0].nested_map_value["key1"].name == "first" error_message = "did not apply mocks" } } diff --git a/internal/command/testing/test_provider.go b/internal/command/testing/test_provider.go index 2f921975b3..3feda5ea9b 100644 --- a/internal/command/testing/test_provider.go +++ b/internal/command/testing/test_provider.go @@ -5,6 +5,7 @@ package testing import ( "fmt" + "maps" "path" "strings" "sync" @@ -20,6 +21,76 @@ import ( ) var ( + // withBlockTypeAttributes contains additional block type attributes that are used across + // different resources and types, so this function serves as a place to store the shared attributes. + withBlockTypeAttributes = func(original map[string]*configschema.Attribute) map[string]*configschema.Attribute { + attrs := map[string]*configschema.Attribute{ + "list_value": { + Type: cty.List(cty.Object(map[string]cty.Type{ + "name": cty.String, + "value": cty.String, + })), + Computed: true, + Optional: true, + }, + "set_value": { + Type: cty.Set(cty.Object(map[string]cty.Type{ + "name": cty.String, + "value": cty.String, + })), + Computed: true, + Optional: true, + }, + "map_value": { + Type: cty.Map(cty.Object(map[string]cty.Type{ + "name": cty.String, + "value": cty.String, + })), + Computed: true, + Optional: true, + }, + + // The below nested_* attributes represent config supporting + // attributes as nested blocks, where terraform interprets the nested blocks + // as attributes within the schema + "nested_list_value": { + Computed: true, + Optional: true, + NestedType: &configschema.Object{ + Nesting: configschema.NestingList, + Attributes: map[string]*configschema.Attribute{ + "name": {Type: cty.String, Optional: true}, + "value": {Type: cty.String, Optional: true}, + }, + }, + }, + "nested_set_value": { + Computed: true, + Optional: true, + NestedType: &configschema.Object{ + Nesting: configschema.NestingSet, + Attributes: map[string]*configschema.Attribute{ + "name": {Type: cty.String, Optional: true}, + "value": {Type: cty.String, Optional: true}, + }, + }, + }, + "nested_map_value": { + Computed: true, + Optional: true, + NestedType: &configschema.Object{ + Nesting: configschema.NestingMap, + Attributes: map[string]*configschema.Attribute{ + "name": {Type: cty.String, Optional: true}, + "value": {Type: cty.String, Optional: true}, + }, + }, + }, + } + maps.Copy(original, attrs) + return original + } + ProviderSchema = &providers.GetProviderSchemaResponse{ Provider: providers.Schema{ Body: &configschema.Block{ @@ -44,6 +115,20 @@ var ( }, }, }, + "test_complex_resource": { + Body: &configschema.Block{ + Attributes: withBlockTypeAttributes(map[string]*configschema.Attribute{ + "id": {Type: cty.String, Optional: true, Computed: true}, + "value": {Type: cty.String, Optional: true}, + "interrupt_count": {Type: cty.Number, Optional: true}, + "destroy_fail": {Type: cty.Bool, Optional: true, Computed: true}, + "create_wait_seconds": {Type: cty.Number, Optional: true}, + "destroy_wait_seconds": {Type: cty.Number, Optional: true}, + "write_only": {Type: cty.String, Optional: true, WriteOnly: true}, + "defer": {Type: cty.Bool, Optional: true}, + }), + }, + }, }, DataSources: map[string]providers.Schema{ "test_data_source": { @@ -69,73 +154,11 @@ var ( "test_complex_data_source": { Body: &configschema.Block{ - Attributes: map[string]*configschema.Attribute{ + Attributes: withBlockTypeAttributes(map[string]*configschema.Attribute{ "id": {Type: cty.String, Required: true}, "value": {Type: cty.String, Computed: true}, "write_only": {Type: cty.String, Optional: true, WriteOnly: true}, - "list_value": { - Type: cty.List(cty.Object(map[string]cty.Type{ - "name": cty.String, - "value": cty.String, - })), - Computed: true, - Optional: true, - }, - "set_value": { - Type: cty.Set(cty.Object(map[string]cty.Type{ - "name": cty.String, - "value": cty.String, - })), - Computed: true, - Optional: true, - }, - "map_value": { - Type: cty.Map(cty.Object(map[string]cty.Type{ - "name": cty.String, - "value": cty.String, - })), - Computed: true, - Optional: true, - }, - - // The below nested_* attributes represent config supporting - // attributes as nested blocks, where terraform interprets the nested blocks - // as attributes within the schema - "nested_list_value": { - Computed: true, - Optional: true, - NestedType: &configschema.Object{ - Nesting: configschema.NestingList, - Attributes: map[string]*configschema.Attribute{ - "name": {Type: cty.String, Optional: true}, - "value": {Type: cty.String, Optional: true}, - }, - }, - }, - "nested_set_value": { - Computed: true, - Optional: true, - NestedType: &configschema.Object{ - Nesting: configschema.NestingSet, - Attributes: map[string]*configschema.Attribute{ - "name": {Type: cty.String, Optional: true}, - "value": {Type: cty.String, Optional: true}, - }, - }, - }, - "nested_map_value": { - Computed: true, - Optional: true, - NestedType: &configschema.Object{ - Nesting: configschema.NestingMap, - Attributes: map[string]*configschema.Attribute{ - "name": {Type: cty.String, Optional: true}, - "value": {Type: cty.String, Optional: true}, - }, - }, - }, - // We never actually reference these values from a data // source, but we have tests that use the same cty.Value // to represent a test_resource and a test_data_source @@ -146,7 +169,7 @@ var ( "create_wait_seconds": {Type: cty.Number, Computed: true}, "destroy_wait_seconds": {Type: cty.Number, Computed: true}, "defer": {Type: cty.Bool, Computed: true}, - }, + }), }, }, },