testtools

package module
v0.0.0-...-e995d3a Latest Latest
Warning

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

Go to latest
Published: Jun 7, 2022 License: Apache-2.0 Imports: 17 Imported by: 1

Documentation

Overview

Package testtools provides a set of tools to help test code that calls AWS services.

**AWS Middleware Stubber**

The AWS Middleware Stubber is a unit testing tool that hooks into the AWS SDK for Go middleware (https://aws.github.io/aws-sdk-go-v2/docs/middleware/) to short-circuit calls to AWS services, verify inputs, and return predefined outputs. This improves unit testing because you don't have to define mocks or change the way your code calls AWS. Tests run without calling AWS, which means tests run faster and don't incur charges or risk impacting your resources.

To use AwsmStubber, first create an instance of AwsmStubber.

stubber := testtools.NewStubber()

The stubber is configured to handle all calls to AWS before the Serialize middleware step. Use the stubber config to create a service client.

client := dynamodb.NewFromConfig(*stubber.SdkConfig)

Define and add all service actions that are called by your test.

  stubber.Add(testtools.Stub{
		OperationName: "GetItem",
		Input: &dynamodb.GetItemInput{ TableName: aws.String(tableName), Key: key },
		Output: &dynamodb.GetItemOutput{Item: map[string]types.AttributeValue{
			"title": &types.AttributeValueMemberS{Value: title},
			"year": &types.AttributeValueMemberN{Value: year},
			"info": &types.AttributeValueMemberM{Value: map[string]types.AttributeValue{
				"rating": &types.AttributeValueMemberN{Value: rating},
				"plot": &types.AttributeValueMemberS{Value: plot},
			}},
		}},
		Error: raiseErr,
	}

During your test run, the stubber verifies that each call is made in the order that stubs are added to the stubber. The stubber also checks actual input against expected input. If the call is verified, either the specified output is returned or, if an error is requested, the error is returned.

Run your test and verify the results. Use testtools helper functions to verify errors and run exit code.

gotMovie, err := basics.GetMovie(movie.Title, movie.Year)

testtools.VerifyError(err, raiseErr, t)
if err == nil {
  if gotMovie.Title != movie.Title || gotMovie.Year != movie.Year {
    t.Errorf("got %s but expected %s", gotMovie, movie)
  }
}

testtools.ExitTest(stubber, t)

By using sub tests, you can use the same test code to test both error and non-error paths.

func TestTableBasics_GetMovie(t *testing.T) {
  t.Run("NoErrors", func (t *testing.T) { GetMovie(nil, t) })
  t.Run("TestError", func (t *testing.T) { GetMovie(&testtools.StubError{Err: errors.New("TestError")}, t)})
}

The testtools.ExitTest helper verifies that all expected stubs were called during the test, so if your test exits early and leaves uncalled stubs, the test fails.

**Framework**

The framework section of the package provides a set of helper functions that you can use in your tests to perform common tasks, such as verifying that errors returned from the code under test match up with the expected errors, and running exit checks to verify all stubs were called.

**Scenarios**

The scenarios section of the package provides a set of helper functions that you can use to run scenario tests. Scenarios typically string together several actions in a narrative format. The scenario test functions let you define the expected actions of your scenario as a list of stubs. Then, your test function is called first with no errors, and subsequently with each stub set to return an error.

**Mocks**

The mocks section of the package provides mocks of components that are used in the code examples, such as a mock of the IQuestioner interface that lets you specify a list of expected answers. The mock questioner returns these answers in sequence during a test to mock user input.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ExitTest

func ExitTest(stubber *AwsmStubber, t *testing.T)

ExitTest is a helper function that verifies that all calls specified in the stubber were called by your test.

func RunScenarioTests

func RunScenarioTests(scenarioTest IScenarioTest, t *testing.T)

RunScenarioTests runs the scenario multiple times. The first time, it runs with no errors. In subsequent runs, it specifies that each stub in the sequence should raise an error, and it verifies the results.

func SubTestRunScenario

func SubTestRunScenario(scenarioTest IScenarioTest, stubs []Stub, stubErr *StubError, t *testing.T)

SubTestRunScenario performs a single test run with a set of stubs that are set up to run with or without errors.

func VerifyError

func VerifyError(actual error, raised *StubError, t *testing.T, handled ...interface{})

VerifyError is a helper function that verifies actual errors against expected errors. You can call it immediately after you call the code you're testing to verify actual errors against expected errors.

If an error is raised but none are expected, the test fails.

If no error is raised but one is expected, the test fails.

If an error is expected to be raised by the stubber and handled by the code under test, but the test returns an error, the test fails.

If an error is raised of a different type than the expected error, the test fails.

If an error other than a smithy.OperationError is raised, the test fails.

Otherwise, the test passes.

Types

type AwsmStubber

type AwsmStubber struct {
	SdkConfig *aws.Config
	// contains filtered or unexported fields
}

AwsmStubber creates a config that has a function inserted into the AWS SDK for Go middleware chain. The stubber expects to be called once for each stub in the contained slice of stubs.

func NewStubber

func NewStubber() *AwsmStubber

NewStubber returns a new stubber that inserts a function before the Serialize step in the middleware chain. The function intercepts service actions and returns stubbed data instead of calling the actual AWS service.

func (*AwsmStubber) Add

func (stubber *AwsmStubber) Add(stub Stub)

Add adds a stub to the end of the slice of stubs.

func (*AwsmStubber) Clear

func (stubber *AwsmStubber) Clear()

Clear removes all stubs from the stubber.

func (*AwsmStubber) MiddlewareStub

MiddlewareStub is a middleware function that is inserted before the Serialize step in the middleware chain.

It gets the next stub in the slice and compares its expected operation with the actual service operation. If they don't match, or if there are no more stubs in the slice, it returns an error.

If the operations match, the actual input is compared against the expected input. If they don't match, it returns an error.

If an error is specified on the stub, the error is returned. If ContinueAfter is false, the rest of the stubs are cleared from the stubber. By using this setting, you can write tests that stop on an error or that handle errors and continue processing.

If the actual operation and input matches the expected operation and input, the function serializes the stubbed output and returns it. This creates a short circuit in the middleware chain so that no requests are made to AWS.

func (*AwsmStubber) Next

func (stubber *AwsmStubber) Next() *Stub

Next returns the next stub in the slice of stubs.

func (*AwsmStubber) VerifyAllStubsCalled

func (stubber *AwsmStubber) VerifyAllStubsCalled() error

VerifyAllStubsCalled returns an error if there are stubs in the slice that were not called. In this way, you can verify that your test made all the calls that you expected.

type IScenarioTest

type IScenarioTest interface {
	SetupDataAndStubs() []Stub
	RunSubTest(stubber *AwsmStubber)
}

IScenarioTest defines callback functions that an individual scenario test must implement.

SetupDataAndStubs sets up test data specific to the test and returns a list of stubs that specify the expected calls that are made during a scenario run.

RunSubTest runs the actual code under test.

type MockQuestioner

type MockQuestioner struct {
	Answers []string
	// contains filtered or unexported fields
}

MockQuestioner is a mock questioner that can be used to simulate user input during a unit test. Specify a slice of Answers that are returned in sequence during a test run.

func (*MockQuestioner) Ask

func (mock *MockQuestioner) Ask(question string, validators []demotools.IAnswerValidator) string

func (*MockQuestioner) AskBool

func (mock *MockQuestioner) AskBool(question string, expected string) bool

func (*MockQuestioner) AskFloat64

func (mock *MockQuestioner) AskFloat64(question string, validators []demotools.IAnswerValidator) float64

func (*MockQuestioner) AskInt

func (mock *MockQuestioner) AskInt(question string, validators []demotools.IAnswerValidator) int

func (*MockQuestioner) Next

func (mock *MockQuestioner) Next() string

Next returns the next answer in the slice of answers.

type Stub

type Stub struct {
	OperationName string
	Input         interface{}
	Output        interface{}
	SkipErrorTest bool
	Error         *StubError
}

Stub defines a service operation, expected inputs, and outputs for a stubbed service action. When an error is specified, it is returned from the stubbed action. SkipErrorTest is used to skip automated error testing when a stub should not raise an error.

func (Stub) Compare

func (stub Stub) Compare(actual interface{}) error

Compare compares the actual input to a service action against the expected input specified in the stub. If they are not equal according to reflect.DeepEqual, an error is returned.

type StubError

type StubError struct {
	Err           error
	ContinueAfter bool
}

StubError contains an error that is raised by a stub. ContinueAfter specifies whether to continue the test after the error.

func (StubError) Error

func (stubErr StubError) Error() string

Error returns the contained error string.

Jump to

Keyboard shortcuts

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