Skip to content

Commit

Permalink
Add mockery for testing (#253)
Browse files Browse the repository at this point in the history
* Add some unit tests for internal/ddb
* Use mockery for internal/event testing
* Use mockery for internal/objectstore testing
* Use mockery for internal/shared testing
  • Loading branch information
hawx authored Aug 23, 2024
1 parent e8cc344 commit 11ad7fb
Show file tree
Hide file tree
Showing 17 changed files with 1,603 additions and 191 deletions.
12 changes: 12 additions & 0 deletions .mockery.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
with-expecter: true
inpackage: True
dir: "{{.InterfaceDir}}"
mockname: "mock{{.InterfaceName|firstUpper}}"
outpkg: "{{.PackageName}}"
filename: "mock_{{.InterfaceName}}_test.go"
all: true
packages:
github.com/ministryofjustice/opg-data-lpa-store/internal/ddb:
github.com/ministryofjustice/opg-data-lpa-store/internal/event:
github.com/ministryofjustice/opg-data-lpa-store/internal/objectstore:
github.com/ministryofjustice/opg-data-lpa-store/internal/shared:
28 changes: 28 additions & 0 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ require (
github.com/leodido/go-urn v1.4.0
github.com/ministryofjustice/opg-go-common v1.8.0
github.com/stretchr/testify v1.9.0
github.com/vektra/mockery/v2 v2.45.0
)

require (
Expand All @@ -41,14 +42,35 @@ require (
github.com/aws/smithy-go v1.20.3 // indirect
github.com/brunoscheufler/aws-ecs-metadata-go v0.0.0-20221221133751-67e37ae746cd // indirect
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
github.com/chigopher/pathlib v0.19.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/fsnotify/fsnotify v1.6.0 // indirect
github.com/go-logr/logr v1.4.2 // indirect
github.com/go-logr/stdr v1.2.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/grpc-ecosystem/grpc-gateway/v2 v2.20.0 // indirect
github.com/hashicorp/hcl v1.0.0 // indirect
github.com/huandu/xstrings v1.4.0 // indirect
github.com/iancoleman/strcase v0.2.0 // indirect
github.com/inconshreveable/mousetrap v1.1.0 // indirect
github.com/jinzhu/copier v0.3.5 // indirect
github.com/jmespath/go-jmespath v0.4.0 // indirect
github.com/magiconair/properties v1.8.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mitchellh/go-homedir v1.1.0 // indirect
github.com/mitchellh/mapstructure v1.5.0 // indirect
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/rs/zerolog v1.29.0 // indirect
github.com/spf13/afero v1.9.3 // indirect
github.com/spf13/cast v1.5.0 // indirect
github.com/spf13/cobra v1.6.1 // indirect
github.com/spf13/jwalterweatherman v1.1.0 // indirect
github.com/spf13/pflag v1.0.5 // indirect
github.com/spf13/viper v1.15.0 // indirect
github.com/stretchr/objx v0.5.2 // indirect
github.com/subosito/gotenv v1.4.2 // indirect
go.opentelemetry.io/contrib/detectors/aws/ecs v1.28.0 // indirect
go.opentelemetry.io/contrib/propagators/aws v1.28.0 // indirect
go.opentelemetry.io/otel v1.28.0 // indirect
Expand All @@ -58,12 +80,18 @@ require (
go.opentelemetry.io/otel/sdk v1.28.0 // indirect
go.opentelemetry.io/otel/trace v1.28.0 // indirect
go.opentelemetry.io/proto/otlp v1.3.1 // indirect
golang.org/x/mod v0.17.0 // indirect
golang.org/x/net v0.26.0 // indirect
golang.org/x/sync v0.7.0 // indirect
golang.org/x/sys v0.21.0 // indirect
golang.org/x/term v0.21.0 // indirect
golang.org/x/text v0.16.0 // indirect
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d // indirect
google.golang.org/genproto/googleapis/api v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/genproto/googleapis/rpc v0.0.0-20240701130421-f6361c86f094 // indirect
google.golang.org/grpc v1.65.0 // indirect
google.golang.org/protobuf v1.34.2 // indirect
gopkg.in/ini.v1 v1.67.0 // indirect
gopkg.in/yaml.v2 v2.4.0 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect
)
496 changes: 496 additions & 0 deletions go.sum

Large diffs are not rendered by default.

19 changes: 13 additions & 6 deletions internal/ddb/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,22 @@ import (
"github.com/ministryofjustice/opg-data-lpa-store/internal/shared"
)

type dynamodbClient interface {
TransactWriteItems(ctx context.Context, params *dynamodb.TransactWriteItemsInput, optFns ...func(*dynamodb.Options)) (*dynamodb.TransactWriteItemsOutput, error)
PutItem(ctx context.Context, params *dynamodb.PutItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.PutItemOutput, error)
GetItem(ctx context.Context, params *dynamodb.GetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.GetItemOutput, error)
BatchGetItem(ctx context.Context, params *dynamodb.BatchGetItemInput, optFns ...func(*dynamodb.Options)) (*dynamodb.BatchGetItemOutput, error)
}

type Client struct {
ddb *dynamodb.Client
svc dynamodbClient
tableName string
changesTableName string
}

func New(cfg aws.Config, tableName, changesTableName string) *Client {
return &Client{
ddb: dynamodb.NewFromConfig(cfg),
svc: dynamodb.NewFromConfig(cfg),
tableName: tableName,
changesTableName: changesTableName,
}
Expand Down Expand Up @@ -58,7 +65,7 @@ func (c *Client) PutChanges(ctx context.Context, data any, update shared.Update)
},
}

_, err = c.ddb.TransactWriteItems(ctx, transactInput)
_, err = c.svc.TransactWriteItems(ctx, transactInput)

return err
}
Expand All @@ -69,7 +76,7 @@ func (c *Client) Put(ctx context.Context, data any) error {
return err
}

_, err = c.ddb.PutItem(ctx, &dynamodb.PutItemInput{
_, err = c.svc.PutItem(ctx, &dynamodb.PutItemInput{
TableName: aws.String(c.tableName),
Item: item,
})
Expand All @@ -85,7 +92,7 @@ func (c *Client) Get(ctx context.Context, uid string) (shared.Lpa, error) {
return lpa, err
}

getItemOutput, err := c.ddb.GetItem(ctx, &dynamodb.GetItemInput{
getItemOutput, err := c.svc.GetItem(ctx, &dynamodb.GetItemInput{
TableName: aws.String(c.tableName),
Key: map[string]types.AttributeValue{
"uid": marshalledUid,
Expand All @@ -109,7 +116,7 @@ func (c *Client) GetList(ctx context.Context, uids []string) ([]shared.Lpa, erro
}
}

output, err := c.ddb.BatchGetItem(ctx, &dynamodb.BatchGetItemInput{
output, err := c.svc.BatchGetItem(ctx, &dynamodb.BatchGetItemInput{
RequestItems: map[string]types.KeysAndAttributes{
c.tableName: {
Keys: keys,
Expand Down
189 changes: 189 additions & 0 deletions internal/ddb/client_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,189 @@
package ddb

import (
"context"
"encoding/json"
"errors"
"testing"

"github.com/aws/aws-sdk-go-v2/aws"
"github.com/aws/aws-sdk-go-v2/service/dynamodb"
"github.com/aws/aws-sdk-go-v2/service/dynamodb/types"
"github.com/ministryofjustice/opg-data-lpa-store/internal/shared"
"github.com/stretchr/testify/assert"
mock "github.com/stretchr/testify/mock"
)

var (
ctx = context.WithValue(context.Background(), "for", "testing")
tableName = "a-table"
changesTableName = "a-change-table"
expectedError = errors.New("hey")
)

func TestNew(t *testing.T) {
client := New(aws.Config{}, tableName, changesTableName)

assert.IsType(t, (*dynamodb.Client)(nil), client.svc)
assert.Equal(t, tableName, client.tableName)
assert.Equal(t, changesTableName, client.changesTableName)
}

func TestClientPutChanges(t *testing.T) {
dynamodbClient := newMockDynamodbClient(t)
dynamodbClient.EXPECT().
TransactWriteItems(ctx, &dynamodb.TransactWriteItemsInput{
TransactItems: []types.TransactWriteItem{{
Put: &types.Put{
TableName: aws.String(tableName),
Item: map[string]types.AttributeValue{
"hey": &types.AttributeValueMemberS{Value: "hello"},
},
},
}, {
Put: &types.Put{
TableName: aws.String(changesTableName),
Item: map[string]types.AttributeValue{
"uid": &types.AttributeValueMemberS{Value: "a-uid"},
"applied": &types.AttributeValueMemberS{Value: "2024-01-01Tsomething"},
"author": &types.AttributeValueMemberS{Value: "an-author"},
"type": &types.AttributeValueMemberS{Value: "a-type"},
"change": &types.AttributeValueMemberL{Value: []types.AttributeValue{
&types.AttributeValueMemberM{Value: map[string]types.AttributeValue{
"Key": &types.AttributeValueMemberS{Value: "a-key"},
"Old": &types.AttributeValueMemberB{Value: []byte("old")},
"New": &types.AttributeValueMemberB{Value: []byte("new")},
}},
}},
},
},
}},
}).
Return(nil, expectedError)

client := &Client{
svc: dynamodbClient,
tableName: tableName,
changesTableName: changesTableName,
}

err := client.PutChanges(ctx, map[string]string{"hey": "hello"}, shared.Update{
Uid: "a-uid",
Applied: "2024-01-01Tsomething",
Author: "an-author",
Type: "a-type",
Changes: []shared.Change{
{Key: "a-key", Old: json.RawMessage("old"), New: json.RawMessage("new")},
},
})
assert.Equal(t, expectedError, err)
}

func TestClientPut(t *testing.T) {
dynamodbClient := newMockDynamodbClient(t)
dynamodbClient.EXPECT().
PutItem(ctx, &dynamodb.PutItemInput{
TableName: aws.String(tableName),
Item: map[string]types.AttributeValue{
"hey": &types.AttributeValueMemberS{Value: "hello"},
},
}).
Return(nil, expectedError)

client := &Client{
svc: dynamodbClient,
tableName: tableName,
}

err := client.Put(ctx, map[string]string{"hey": "hello"})
assert.Equal(t, expectedError, err)
}

func TestClientGet(t *testing.T) {
dynamodbClient := newMockDynamodbClient(t)
dynamodbClient.EXPECT().
GetItem(ctx, &dynamodb.GetItemInput{
TableName: aws.String(tableName),
Key: map[string]types.AttributeValue{
"uid": &types.AttributeValueMemberS{Value: "my-uid"},
},
}).
Return(&dynamodb.GetItemOutput{
Item: map[string]types.AttributeValue{
"uid": &types.AttributeValueMemberS{Value: "my-uid"},
"lpaType": &types.AttributeValueMemberS{Value: "property-and-affairs"},
},
}, nil)

client := &Client{
svc: dynamodbClient,
tableName: tableName,
}

lpa, err := client.Get(ctx, "my-uid")
assert.Nil(t, err)
assert.Equal(t, shared.Lpa{Uid: "my-uid", LpaInit: shared.LpaInit{LpaType: shared.LpaTypePropertyAndAffairs}}, lpa)
}

func TestClientGetWhenClientErrors(t *testing.T) {
dynamodbClient := newMockDynamodbClient(t)
dynamodbClient.EXPECT().
GetItem(ctx, mock.Anything).
Return(nil, expectedError)

client := &Client{svc: dynamodbClient}

_, err := client.Get(ctx, "my-uid")
assert.Equal(t, expectedError, err)
}

func TestClientGetList(t *testing.T) {
dynamodbClient := newMockDynamodbClient(t)
dynamodbClient.EXPECT().
BatchGetItem(ctx, &dynamodb.BatchGetItemInput{
RequestItems: map[string]types.KeysAndAttributes{
tableName: {
Keys: []map[string]types.AttributeValue{{
"uid": &types.AttributeValueMemberS{Value: "my-uid"},
}, {
"uid": &types.AttributeValueMemberS{Value: "another-uid"},
}},
},
},
}).
Return(&dynamodb.BatchGetItemOutput{
Responses: map[string][]map[string]types.AttributeValue{
tableName: []map[string]types.AttributeValue{{
"uid": &types.AttributeValueMemberS{Value: "my-uid"},
"lpaType": &types.AttributeValueMemberS{Value: "property-and-affairs"},
}, {
"uid": &types.AttributeValueMemberS{Value: "another-uid"},
"lpaType": &types.AttributeValueMemberS{Value: "personal-welfare"},
}},
},
}, nil)

client := &Client{
svc: dynamodbClient,
tableName: tableName,
}

lpas, err := client.GetList(ctx, []string{"my-uid", "another-uid"})
assert.Nil(t, err)
assert.Equal(t, []shared.Lpa{
{Uid: "my-uid", LpaInit: shared.LpaInit{LpaType: shared.LpaTypePropertyAndAffairs}},
{Uid: "another-uid", LpaInit: shared.LpaInit{LpaType: shared.LpaTypePersonalWelfare}},
}, lpas)
}

func TestClientGetListWhenClientErrors(t *testing.T) {
dynamodbClient := newMockDynamodbClient(t)
dynamodbClient.EXPECT().
BatchGetItem(ctx, mock.Anything).
Return(nil, expectedError)

client := &Client{svc: dynamodbClient}

_, err := client.GetList(ctx, []string{"my-uid", "another-uid"})
assert.Equal(t, expectedError, err)
}
Loading

0 comments on commit 11ad7fb

Please sign in to comment.