1

I'm studying Terraform and as a test lover I'm using Terratest to test it out but, I'm not being able to mock Terraform's functions such as timestamp(). Tried some stuffs such as use the library monkey for mocking but so far, none of my approches worked.

Does anyone have an idea about how to mock terraform's functions for testing proposals?

Here a small example that can exemplify my question:

file: main.tf

locals {
  creation_time = formatdate("YYYYMMDDhhmmss", timestamp())
}

file: outputs.tf

output "CreationDate" {
  value = local.creation_time,
  description = "Bla bla bla"
}

./tests/main_test.go

package study

import (
  "testing"
  "github.com/stretchr/testify/assert"
  "github.com/stretchr/terratest/modules/terraform"
  "bou.ke/monkey"
)

func Test(t * testing.T) {
  t.Parallel()

  terraformOptions := &terraform.Options{
    TerraformDir" "../",
  }

  monkey.Patch(time.Now, func() time.Time {
    return time.Date(2022, 12, 8, 23, 59, 1, time.UTC)
  })

  defer terraform.Destroy(t, terraformOptions)
  terraform.InitAndApply(t, terraformOptions)

  output = terraform.Output(t, terraformOptions, "CreationDate")
  assert.Equal(t, "20221208235901", output)
}

Super simplified example about how to run it:

go mod init study
go mod tidy
cd tests
go test

So, I'm expecting to mock a function from Terraform and assert this value to make sure terraform's file/module does what's expected.

Matthew Schuchard
  • 25,172
  • 3
  • 47
  • 67
lucAlucard
  • 91
  • 1
  • 2
  • I would have recommended using the TF function directly, but I tested it out and it is internal to the Terraform package, and therefore its import is not allowed. Otherwise it would be straightforward to implement. – Matthew Schuchard Dec 08 '22 at 13:50
  • HI @MattSchuchard thanks for your reply. Do you think test these internal functions is even possible? I'm checking Terraform's code on github to check if I'm able to find some internal function that it would be possible to mock it, but so far still not being able to test it. – lucAlucard Dec 08 '22 at 14:24
  • Well it is definitely possible because the functions have associated unit tests in the Terraform package. However, these are acceptance tests with Terratest. Either way, you are testing your TF config here and not the TF function, so I would probably focus on that. – Matthew Schuchard Dec 08 '22 at 14:39

1 Answers1

0

Unlike some other languages, the Terraform language does not support this sort "monkey patch"-style mocking where you unilaterally change the definition of something for the entire program.

Terraform modules can their behavior only based on input variables and provider behaviors, so you can add optional features to your module to make it explicitly configurable, if you wish:

variable "override_timestamp" {
  type    = string
  default = null
}

locals {
  creation_time = coalesce(var.override_timestamp, timestamp())
}

Of course, this technique will not test that your module is actually calling timestamp in the normal case, so it's questionable whether this would actually be useful for testing.

It might be more profitable to instead design your test driver to verify that the timestamp has overall correct syntax and then do some fuzzy matching on it, such as asserting that the reported instant is greater than or equal to the test start time and less than or equal to the test end time.

Martin Atkins
  • 62,420
  • 8
  • 120
  • 138