hashicorp / terraform-plugin-sdk

Terraform Plugin SDK enables building plugins (providers) to manage any service providers or custom in-house solutions
https://developer.hashicorp.com/terraform/plugin
Mozilla Public License 2.0
442 stars 232 forks source link

How to set change on schema.ResourceData to make unit testing update functions easier? #221

Open nmiodice opened 5 years ago

nmiodice commented 5 years ago

Seeking guidance on setting up schema.ResourceData to return true when d.HasChange("foo") is called, and also to set the change data returned from d.Change("foo").

I have an update function for a resource that I want to test. The (simplified) logic looks like:

if !d.HasChange("members") {
    return nil
}
old, new := d.Change("members")
...

In my unit tests, I'm configuring schema.ResourceData for other cases like so:

schema.TestResourceDataRaw(t, resourceSchema, resourceDataMap)

How can I set the new/old data so that I can unit test my update code? For reference, I'm working on a provider for Azure DevOps: https://github.com/microsoft/terraform-provider-azuredevops. The piece of code I am having trouble testing is here: https://github.com/microsoft/terraform-provider-azuredevops/blob/49cb63cf9eea3981cac06104afa766d756cf97d4/azuredevops/resource_group_membership.go#L54-L63

invidian commented 4 years ago

Hey @paultyng, not sure if it's still relevant, but I think I found a way to actually test it. I had a problem with schema.TestResourceDataRaw, as it seems it only creates the ResourceData, but it seems it's not being persisted, so it's like a new configured resource, rather than a resource, which you are going to change/destroy. To make it shows like it's already in the state, I do the following in my project:

  // Create ResourceData object.
  d := schema.TestResourceDataRaw(t, r.Schema, raw)

  // Mark newly created object as created, so it's state is persisted.
  d.SetId("foo")

  // Create new ResourceData from the state, so it's persisted and there is no diff included.
  dn := r.Data(d.State())

If you don't call SetID, then output of d.State() is different, as it is empty. github.com/google/go-cmp/cmp is extremely helpful here, to see what is going on. I use it with e.g. cmp.Diff(nil, d.State). In this snippet, dn (data new) is something you would pass to Update functions etc.