integration

package
v0.0.18 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Oct 21, 2025 License: MIT, Apache-2.0 Imports: 20 Imported by: 0

README

Integration

The integration package provides a library for writing integration tests for your provider code. It enables testing provider behavior in-memory, sitting just above the gRPC level. This package is particularly useful for validating the lifecycle of resources and ensuring correctness in provider implementations.

Server

The package includes a Server interface and its implementation, which acts as a test harness for Pulumi providers. The interface allows you to exercise the RPC methods of your provider, including:

  • Schema retrieval
  • Provider configuration
  • Resource lifecycle operations (create, read, update, delete)
  • Component lifecycle operations (construct)
  • Provider functions (invoke) and resource functions (call)

To make a server, call integration.NewServer and use WithProvider to pass the Provider instance to be tested. Then, exercise the various RPC methods of your provider.

Component Resource Mocks

Since the business logic of a component typically creates child resources, testing the logic usually involves mocking the implementation of child resources. For example, if your component creates a random.RandomPet resource, you can use a mock to return simulated resource state, i.e. the RandomPet.ID property. The actual random provider is never called.

To configure mocking, use the integration.WithMocks server option and pass an implementation of pulumi.MockResourceMonitor. The mock monitor receives a callback for the component resource and for each child resource as it is registered, giving you an opportunity to return a simulated state for each child. See integation.MockResourceMonitor for a simple implementation.

To test a component resource, call the Construct method on the integration server.

import (
	"testing"

	"github.com/stretchr/testify/require"

	p "github.com/pulumi/pulumi-go-provider"
	"github.com/pulumi/pulumi-go-provider/integration"
	r "github.com/pulumi/pulumi/sdk/v3/go/common/resource"
	"github.com/pulumi/pulumi/sdk/v3/go/property"
	"github.com/pulumi/pulumi/sdk/v3/go/pulumi"
)

func TestConstruct(t *testing.T) {
    myProvider, err := infer.NewProviderBuilder().
		WithComponents(
			infer.ComponentF(MyComponent),
		).
		Build()
	require.NoError(t, err)

	server, err := integration.NewServer(
		t.Context(),
		"example",
		semver.MustParse("1.0.0"),
		integration.WithProvider(myProvider),
        integration.WithMocks(&integration.MockResourceMonitor{
			NewResourceF: func(args integration.MockResourceArgs) (string, property.Map, error) {
				// NewResourceF is called as the each resource is registered
				switch {
				case args.TypeToken == "my:module:MyComponent" && args.Name == "my-component":
                default:
                    // make assertions about the component's children and return
                    // a fake id and some resource properties
				}
				return "", property.Map{}, nil
			},
		}),
	)
	require.NoError(t, err)

	// test the "my:module:MyComponent" component
	resp, err := server.Construct(p.ConstructRequest{
		Urn:    "urn:pulumi:stack::project::my:module:MyComponent::my-component",
		Inputs: property.NewMap(map[string]property.Value{
			"pi": property.New(3.14),
		}),
	})
	require.NoError(t, err)
	require.Equal(t, property.NewMap(map[string]property.Value{
		"result": property.New("foo-12345").WithSecret(true),
	}), resp.State)
}

Custom Resource Lifecycle Testing

The LifeCycleTest struct enables testing the full lifecycle of a custom resource, including:

  1. Previewing and creating resources.
  2. Updating resources with new inputs.
  3. Deleting resources.

It supports hooks for custom validation and assertions on resource outputs.

Client Injection

Most providers connect to external systems using a client library of some kind. To test your provider code, you'll need to make a suitable mock client. This section addresses how to inject a client into an infer-style provider.

The provider build syntax allows you to pre-initialize the various receivers. Use this to supply your resources, components, and functions with a logger, client factory, or other variables.

See examples/configurable for a demonstration.

Example
func TestMyResourceLifecycle(t *testing.T) {
	myProvider, err := infer.NewProviderBuilder().
		WithResources(
			infer.Resource(MyResource),
		).
		Build()
	require.NoError(t, err)

	server, err := integration.NewServer(
		t.Context(),
		"example",
		semver.MustParse("1.0.0"),
		integration.WithProvider(myProvider),
	)
	require.NoError(t, err)

	test := integration.LifeCycleTest{
		Resource: "my:module:MyResource",
		Create: integration.Operation{
			Inputs: property.Map{"key": property.New("value")},
			ExpectedOutput: &property.Map{"key": property.New("value")},
		},
	}
	test.Run(t, server)
}

For more details, refer to the source code and comments in the integration.go file, and the battery of test cases in the tests package since the tests are implemented using the integration package.

Documentation

Overview

Package integration is a test library for validating in-memory providers behave correctly.

It sits just above the gRPC level. For full unit testing, see github.com/pulumi/pulumi/pkg/v3/testing/integration.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type LifeCycleTest

type LifeCycleTest struct {
	Resource tokens.Type
	Create   Operation
	Updates  []Operation
}

LifeCycleTest describing the lifecycle of a resource test.

func (LifeCycleTest) Run

func (l LifeCycleTest) Run(t *testing.T, server Server)

Run a resource through it's lifecycle asserting that its output is as expected. The resource is

1. Previewed. 2. Created. 2. Previewed and Updated for each update in the Updates list. 3. Deleted.

type MockCallArgs

type MockCallArgs struct {
	// Token indicates which function is being called. This token is of the form "package:module:function".
	Token tokens.ModuleMember
	// Args are the arguments provided to the function call.
	Args property.Map
	// Provider is the identifier of the provider instance being used to make the call.
	Provider p.ProviderReference
}

MockCallArgs is used to construct a call Mock

type MockResourceArgs

type MockResourceArgs struct {
	// TypeToken is the token that indicates which resource type is being constructed. This token
	// is of the form "package:module:type".
	TypeToken tokens.Type
	// Name is the logical name of the resource instance.
	Name string
	// Inputs are the inputs for the resource.
	Inputs property.Map
	// Provider is the identifier of the provider instance being used to manage this resource.
	Provider p.ProviderReference
	// ID is the physical identifier of an existing resource to read or import.
	ID string
	// Custom specifies whether or not the resource is Custom (i.e. managed by a resource provider).
	Custom bool
	// Full register RPC call, if available.
	RegisterRPC *pulumirpc.RegisterResourceRequest
	// Full read RPC call, if available
	ReadRPC *pulumirpc.ReadResourceRequest
}

MockResourceArgs is a used to construct a newResource Mock

type MockResourceMonitor

type MockResourceMonitor struct {
	CallF        func(args MockCallArgs) (property.Map, error)
	NewResourceF func(args MockResourceArgs) (string, property.Map, error)
}

MockResourceMonitor mocks resource registration and function calls.

func (*MockResourceMonitor) Call

func (*MockResourceMonitor) NewResource

type Operation

type Operation struct {
	// The inputs for the operation
	Inputs property.Map
	// The expected output for the operation. If ExpectedOutput is nil, no check will be made.
	ExpectedOutput *property.Map
	// A function called on the output of this operation.
	Hook func(inputs, output property.Map)
	// If the test should expect the operation to signal an error.
	ExpectFailure bool
	// If CheckFailures is non-nil, expect the check step to fail with the provided output.
	CheckFailures []p.CheckFailure
}

Operation describes a step in a LifeCycleTest.

TODO: Add support for diff verification.

type Server

func NewServer

func NewServer(ctx context.Context, pkg string, version semver.Version,
	opts ...ServerOption,
) (Server, error)

NewServer constructs a gRPC server for testing the given provider.

Must be called with WithProvider or WithProviderF.

type ServerOption

type ServerOption interface {
	// contains filtered or unexported methods
}

func WithMocks

func WithMocks(mocks pulumi.MockResourceMonitor) ServerOption

WithMocks allows injecting mock resources, helpful for testing a component which cretes child resources.

func WithProvider

func WithProvider(p p.Provider) ServerOption

WithProvider backs the server with the given concrete provider.

func WithProviderF

func WithProviderF(p func(*pprovider.HostClient) p.Provider) ServerOption

WithProviderF backs the server with a lazily initialized provider.

Directories

Path Synopsis
Package fake implements a fake pulumirpc.EngineServer and pulumirpc.ResourceMonitorServer for integration test purposes.
Package fake implements a fake pulumirpc.EngineServer and pulumirpc.ResourceMonitorServer for integration test purposes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL