func (fd *Client) GetItem(input *dynamodb.GetItemInput) (*dynamodb.GetItemOutput, error) {
	if err := input.Validate(); err != nil {
		return nil, err
	}
	fd.mu.Lock()
	defer fd.mu.Unlock()
	if fd.forceFailureErr != nil {
		return nil, fd.forceFailureErr
	}
	table, err := fd.getTable(aws.StringValue(input.TableName))
	if err != nil {
		return nil, err
	}
	key, ok := table.keySchema.getKey(table.attributesDef, input.Key)
	if !ok {
		return nil, ErrMissingKeys
	}
	item := copyItem(table.data[key])
	output := &dynamodb.GetItemOutput{
		Item: item,
	}
	return output, nil
}
GetItem mock response for dynamodb
package minidyn
import (
	"errors"
	"sync"
	"github.com/aws/aws-sdk-go/aws"
	"github.com/aws/aws-sdk-go/aws/awserr"
	"github.com/aws/aws-sdk-go/aws/request"
	"github.com/aws/aws-sdk-go/service/dynamodb"
	"github.com/aws/aws-sdk-go/service/dynamodb/dynamodbiface"
	"github.com/truora/minidyn/interpreter"
)
const primaryIndexName = ""
var (
	ErrMissingKeys = awserr.New("ValidationException", "The number of conditions on the keys is invalid", nil)
	ErrInvalidTableName = errors.New("invalid table name")
	ErrResourceNotFoundException = errors.New("requested resource not found")
	ErrConditionalRequestFailed = errors.New("the conditional request failed")
	ReturnUnprocessedItemsInBatch = false
)
type Client struct {
	dynamodbiface.DynamoDBAPI
	tables                map[string]*table
	mu                    sync.Mutex
	itemCollectionMetrics map[string][]*dynamodb.ItemCollectionMetrics
	langInterpreter       *interpreter.Language
	nativeInterpreter     *interpreter.Native
	forceFailureErr       error
}
func NewClient() *Client {
	fake := Client{
		tables:            map[string]*table{},
		mu:                sync.Mutex{},
		nativeInterpreter: interpreter.NewNativeInterpreter(),
		langInterpreter:   &interpreter.Language{},
	}
	return &fake
}
func (fd *Client) ActivateDebug() {
	fd.mu.Lock()
	defer fd.mu.Unlock()
	fd.langInterpreter.Debug = true
}
func (fd *Client) setFailureCondition(condition FailureCondition) {
	fd.mu.Lock()
	defer fd.mu.Unlock()
	fd.forceFailureErr = emulatingErrors[condition]
}
func (fd *Client) SetInterpreter(i interpreter.Interpreter) {
	native, ok := i.(*interpreter.Native)
	if !ok {
		panic("invalid interpreter type")
	}
	fd.nativeInterpreter = native
	for _, table := range fd.tables {
		table.nativeInterpreter = native
	}
}
func (fd *Client) GetNativeInterpreter() *interpreter.Native {
	return fd.nativeInterpreter
}
func (fd *Client) CreateTable(input *dynamodb.CreateTableInput) (*dynamodb.CreateTableOutput, error) {
	if err := input.Validate(); err != nil {
		return nil, err
	}
	tableName := aws.StringValue(input.TableName)
	if _, ok := fd.tables[tableName]; ok {
		return nil, awserr.New(dynamodb.ErrCodeResourceInUseException, "Cannot create preexisting table", nil)
	}
	newTable := newTable(tableName)
	newTable.setAttributeDefinition(input.AttributeDefinitions)
	newTable.billingMode = input.BillingMode
	newTable.nativeInterpreter = fd.nativeInterpreter
	newTable.langInterpreter = fd.langInterpreter
	if err := newTable.createPrimaryIndex(input); err != nil {
		return nil, err
	}
	if err := newTable.addGlobalIndexes(input.GlobalSecondaryIndexes); err != nil {
		return nil, err
	}
	if err := newTable.addLocalIndexes(input.LocalSecondaryIndexes); err != nil {
		return nil, err
	}
	fd.tables[tableName] = newTable
	return &dynamodb.CreateTableOutput{
		TableDescription: newTable.description(tableName),
	}, nil
}
func (fd *Client) CreateTableWithContext(ctx aws.Context, input *dynamodb.CreateTableInput, opt ...request.Option) (*dynamodb.CreateTableOutput, error) {
	return fd.CreateTable(input)
}
func (fd *Client) DeleteTable(input *dynamodb.DeleteTableInput) (*dynamodb.DeleteTableOutput, error) {
	if err := input.Validate(); err != nil {
		return nil, err
	}
	tableName := aws.StringValue(input.TableName)
	table, err := fd.getTable(tableName)
	if err != nil {
		return nil, err
	}
	desc := table.description(tableName)
	delete(fd.tables, tableName)
	return &dynamodb.DeleteTableOutput{
		TableDescription: desc,
	}, nil
}
func (fd *Client) DeleteTableWithContext(ctx aws.Context, input *dynamodb.DeleteTableInput, opt ...request.Option) (*dynamodb.DeleteTableOutput, error) {
	return fd.DeleteTable(input)
}
func (fd *Client) UpdateTable(input *dynamodb.UpdateTableInput) (*dynamodb.UpdateTableOutput, error) {
	if err := input.Validate(); err != nil {
		return nil, err
	}
	tableName := aws.StringValue(input.TableName)
	table, ok := fd.tables[tableName]
	if !ok {
		return nil, awserr.New(dynamodb.ErrCodeResourceNotFoundException, "Cannot do operations on a non-existent table", nil)
	}
	if input.AttributeDefinitions != nil {
		table.setAttributeDefinition(input.AttributeDefinitions)
	}
	for _, change := range input.GlobalSecondaryIndexUpdates {
		if err := table.applyIndexChange(change); err != nil {
			return &dynamodb.UpdateTableOutput{
				TableDescription: table.description(tableName),
			}, err
		}
	}
	return &dynamodb.UpdateTableOutput{
		TableDescription: table.description(tableName),
	}, nil
}
func (fd *Client) UpdateTableWithContext(ctx aws.Context, input *dynamodb.UpdateTableInput, opts ...request.Option) (*dynamodb.UpdateTableOutput, error) {
	return fd.UpdateTable(input)
}
func (fd *Client) DescribeTable(input *dynamodb.DescribeTableInput) (*dynamodb.DescribeTableOutput, error) {
	tableName := aws.StringValue(input.TableName)
	table, err := fd.getTable(tableName)
	if err != nil {
		return nil, err
	}
	output := &dynamodb.DescribeTableOutput{
		Table: table.description(tableName),
	}
	return output, nil
}
func (fd *Client) DescribeTableWithContext(ctx aws.Context, input *dynamodb.DescribeTableInput, ops ...request.Option) (*dynamodb.DescribeTableOutput, error) {
	return fd.DescribeTable(input)
}
func (fd *Client) PutItem(input *dynamodb.PutItemInput) (*dynamodb.PutItemOutput, error) {
	if err := input.Validate(); err != nil {
		return nil, err
	}
	fd.mu.Lock()
	defer fd.mu.Unlock()
	if fd.forceFailureErr != nil {
		return nil, fd.forceFailureErr
	}
	table, err := fd.getTable(aws.StringValue(input.TableName))
	if err != nil {
		return nil, err
	}
	item, err := table.put(input)
	return &dynamodb.PutItemOutput{
		Attributes: item,
	}, err
}
func (fd *Client) PutItemWithContext(ctx aws.Context, input *dynamodb.PutItemInput, opts ...request.Option) (*dynamodb.PutItemOutput, error) {
	return fd.PutItem(input)
}
func (fd *Client) DeleteItem(input *dynamodb.DeleteItemInput) (*dynamodb.DeleteItemOutput, error) {
	if err := input.Validate(); err != nil {
		return nil, err
	}
	fd.mu.Lock()
	defer fd.mu.Unlock()
	if fd.forceFailureErr != nil {
		return nil, fd.forceFailureErr
	}
	table, err := fd.getTable(aws.StringValue(input.TableName))
	if err != nil {
		return nil, err
	}
	if input.ConditionExpression != nil {
		items, _ := table.searchData(queryInput{
			Index:                     primaryIndexName,
			ExpressionAttributeValues: input.ExpressionAttributeValues,
			Aliases:                   input.ExpressionAttributeNames,
			Limit:                     aws.Int64(1),
			ConditionExpression:       input.ConditionExpression,
		})
		if len(items) == 0 {
			return &dynamodb.DeleteItemOutput{}, awserr.New(dynamodb.ErrCodeConditionalCheckFailedException, ErrConditionalRequestFailed.Error(), nil)
		}
	}
	item, err := table.delete(input)
	if err != nil {
		return nil, err
	}
	if aws.StringValue(input.ReturnValues) == "ALL_OLD" {
		return &dynamodb.DeleteItemOutput{
			Attributes: item,
		}, nil
	}
	return &dynamodb.DeleteItemOutput{}, nil
}
func (fd *Client) DeleteItemWithContext(ctx aws.Context, input *dynamodb.DeleteItemInput, opts ...request.Option) (*dynamodb.DeleteItemOutput, error) {
	return fd.DeleteItem(input)
}
func (fd *Client) UpdateItem(input *dynamodb.UpdateItemInput) (*dynamodb.UpdateItemOutput, error) {
	if err := input.Validate(); err != nil {
		return nil, err
	}
	fd.mu.Lock()
	defer fd.mu.Unlock()
	if fd.forceFailureErr != nil {
		return nil, fd.forceFailureErr
	}
	table, err := fd.getTable(aws.StringValue(input.TableName))
	if err != nil {
		return nil, err
	}
	item, err := table.update(input)
	if err != nil {
		return nil, err
	}
	output := &dynamodb.UpdateItemOutput{
		Attributes: item,
	}
	return output, nil
}
func (fd *Client) UpdateItemWithContext(ctx aws.Context, input *dynamodb.UpdateItemInput, opts ...request.Option) (*dynamodb.UpdateItemOutput, error) {
	return fd.UpdateItem(input)
}