1

I have a go project where I am having a query method called "queryMyTable". Here is the code for the method.

func queryMyTable(ctx context.Context, dynamodbClient *dynamodb.Client, tableName string, ids []string) (*dynamodb.QueryOutput, error) {

    // The filterExpression will be constructed based on the ids. Ex: "id IN (:id1,:id2)"
    filterExpression := constructFilterExpression(ids)

    // The expressionAttributeValues will be constructed based on the ids. 
    // It is of type map[string]types.AttributeValue
    // expressionAttributeValues = map[string]types.AttributeValue{
    //    "my-key": &types.AttributeValueS(Value: "my-key-value"),
    //    "id1": &types.AttributeValueS(Value: "111"),
    //    "id2": &types.AttributeValueS(Value: "222"),
    // }
    expressionAttributeValues := constructExpressionAttributeValues(ids)

    // Construct the query
    queryInput := &dynamodb.QueryInput{
        TableName:                 aws.String("my-ddb-table"),
        IndexName:                 aws.String("my-key-index"),
        KeyConditionExpression:    aws.String("my-key = :my-key"),
        FilterExpression:          aws.String(filterExpression),
        ExpressionAttributeValues: expressionAttributeValues,
        ProjectionExpression:      aws.String("id,list"),
    }

    // Execute the query
    result, err := dynamodbClient.Query(ctx, queryInput)
    if err != nil {
        return nil, err
    }

    // Return the results
    return result, nil
}

The sample data for the input parameters are: The filterExpression will be constructed based on the ids.

filterExpression = "id IN (:id1,:id2)"

The expressionAttributeValues will be constructed based on the ids.

expressionAttributeValues = map[string]types.AttributeValue{
  "my-key": &types.AttributeValueS(Value: "my-key-value"),
  "id1": &types.AttributeValueS(Value: "111"),
  "id2": &types.AttributeValueS(Value: "222"),
}

The code is working fine and I have written tests for constructFilterExpression and constructExpressionAttributeValues.

Now, I want to write unit test cases for this method. I am using "aws-sdk-go-v2" and I am not sure how to mock a dynamodb client and setup data for my tests and execute the query method against the mock data.

I tried with this test code


// MockDynamoDBClient is a mock implementation of the DynamoDB client
type MockDynamoDBClient struct {
    dynamodb.Client
    QueryFunc          func(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error)
    QueryRequestInput  *dynamodb.QueryInput
    QueryResponseData  *dynamodb.QueryOutput
    QueryResponseError error
}

// Query mocks the Query method of the DynamoDB client
func (m *MockDynamoDBClient) Query(ctx context.Context, params *dynamodb.QueryInput, optFns ...func(*dynamodb.Options)) (*dynamodb.QueryOutput, error) {
    if m.QueryFunc != nil {
        return m.QueryFunc(ctx, params, optFns...)
    }

    // Store the executed query parameters for assertions in the test
    m.QueryRequestInput = params

    // Return the stored response data or error
    return m.QueryResponseData, m.QueryResponseError
}

But when I executed my query method inside the test method it gave me error obviously

output, err := queryVPNConfigurations(context.Background(), &mockClient.Client, "test-table-name", []string{"111","222"})

Error: operation error DynamoDB: Query, expected endpoint resolver to not be nil. Then I tried setup and endpointresolver and failed again. I am not sure, if this is the way it has to be done.

Any help is appreciated.

davidbilla
  • 2,120
  • 1
  • 15
  • 26
  • Consider to create interface for the client and generate mock with https://github.com/uber/mock. Ref: https://aws.github.io/aws-sdk-go-v2/docs/unit-testing/ – Tony Yip Jul 15 '23 at 20:13
  • I'm a newbie to mock tests. Maybe a dumb question this is. What is the general approach here? Do we create a mock instance of the dynamodb, put some mock test data to it and execute the test method to query against the mock test data OR do we execute the test against the actual dynamodb in AWS account, get the results and assert against the mock expected results? – davidbilla Jul 16 '23 at 02:52
  • Please check the document on aws.github.io/aws-sdk-go-v2/docs/unit-testing, there is an example about mocking AWS client, you don't need an AWS account for this – Tony Yip Jul 17 '23 at 14:51
  • @TonyYip Thank you. Just to clarify, I have to do a `&dynamodb.CreateTable`, put my data into it using `&dynamodb.PutItemRequest` and then query using the `&dynamodb.QueryInput`? – davidbilla Jul 20 '23 at 08:35

0 Answers0