# AWS Service Client Mocks

Because mocking is hard and all I really want is to force errors to happen... most of the time.

## Basic Usage

```go
import "code.justin.tv/eventbus/controlplane/infrastructure/mocks"

func TestShowExampleMockUsage(t *testing.T) {
    mockSQS := mocks.NewMockSQS()
    ctx := mocks.DefaultBehavior()

    defaultResp := &sqs.GetQueueAttributesOutput{} // your default happy path return value

    // Define a default behavior for the API calls we intend to use
    mockSQS.On("GetQueueAttributesWithContext", mock.MatchedBy(mocks.IsDefaultBehavior(mocks.SQSGetQueueAttributes)), mock.Anything, mock.Anything).Return(defaultResp, nil)
    
    // Use the behavior in the context to tease out the right behavior from a given API call
    req := &sqs.GetQueueAttributesInput{}
    mockSQS.GetQueueAttributesWithContext(ctx, req) // returns (defaultResp, nil)
    mockSQS.GetQueueAttributesWithContext(mocks.WithBehavior(ctx, mocks.SQSGetQueueAttributes, mocks.Error), req) // returns (nil, error)

    // Use a custom behavior to cause a custom response
    myBehavior := "custom-get-queue-attributes-behavior"
    myResp := &sqs.GetQueueAttributesOutput{}
    mockSQS.On("GetQueueAttributesWithContext", mock.MatchedBy(mocks.IsBehavior(mocks.SQSGetQueueAttributes, myBehavior)), mock.Anything, mock.Anything).Return(myResp, nil)
    mockSQS.GetQueueAttributesWithContext(mocks.WithBehavior(ctx, mocks.SQSGetQueueAttributes, myBehavior), req) // returns (myResp, nil)
}
```

## Default, Error, and Custom Behaviors

When creating a mock from this package, you will receive a struct that has the subset of AWS API calls we use implemented using the testify mocking package.

You, the user, are responsible for providing, for each method you intend to use in your test, a "default" behavior. See the example above for setting a default behavior on a particular API method.

For errors, the mock comes with a `mocks.Error` behavior for each API method which returns a canned error response. These errors can be invoked by running your test with a context that has the corresponding behavior constant set for that API you wish to error. For example, `mocks.NewMockSQS()` comes with a `On(...)` stub for `GetQueueAttributesWithContext` which allows errors to be surfaced when the provided context is `mocks.WithBehavior(ctx, mocks.SQSGetQueueAttributes, mocks.Error)`. In this case, `mocks.SQSGetQueueAttributes` is the API we are setting a behavior for, and `mocks.Error` is the indication that we want the API to return a generic error.

To use a custom behavior, define a unique key (string) to identify the behavior. Then, use `myMock.On("methodToMock", mock.MatchedBy(mocks.IsBehavior(MethodConstant, myCustomKey)), <more args>).Return(<custom return values>)`. When calling the function being tested, pass context like so: `functionBeingTested(mocks.WithBehavior(ctx, MethodConstant, myCustomKey), <more function args>)`. The `mocks` package contains a `MethodConstant` (e.g. `SQSGetQueueAttributes`) for each AWS API in use, prefixed by AWS service name.