Макет контекста. Контент для проверки lambdacontext.FromContext - PullRequest
0 голосов
/ 23 мая 2018

Я создаю Ams-лямбду, используя aws-sdk-go и aws-lambda-go , и я застрял с небольшой проблемой.

Я хочу проверить мой лямбда-обработчик.Для этого мне нужно смоделировать действительный context.Context , содержащий действительные атрибуты для lamdacontext.LambdaContext и удовлетворить lambdacontext.FromContext.

Я не могу найтиспособ создать такой макет, так как lambdacontext.FromContext всегда возвращает меня _, false.

Вот мой основной, с простым обработчиком для events.SNSEvent event:

package main

import (
    "context"
    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambda"
    "github.com/aws/aws-lambda-go/lambdacontext"
)

func main() {
    lambda.Start(handleRequest)
}

func handleRequest(ctx context.Context, snsEvent events.SNSEvent) error {
    lc, ok := lambdacontext.FromContext(ctx); if !ok {
        // Always false
        ...
        return someErr
    }
    . . .
    return nil
}

И вот мой тест для handleRequest:

package main

import (
    "context"
    "github.com/aws/aws-lambda-go/events"
    "github.com/aws/aws-lambda-go/lambdacontext"
    "github.com/stretchr/testify/assert"
    "gitlab.easy-network.it/meg/aml-rekognition/testdata"
    "testing"
)

const imgMock = `
{
  \"some_parameter\": \"some_value\"
}`

func TestHandleRequest(t *testing.T) {

    c := context.Background()

    ctxV := context.WithValue(c, "", map[string]interface{}{
        "AwsRequestID" : "some_aws_id",
        "InvokedFunctionArn" : "some_arn",
        "Identity" : lambdacontext.CognitoIdentity{},
        "ClientContext" : lambdacontext.ClientContext{},
    })

    snsEventMock := events.SNSEvent{
        Records: []events.SNSEventRecord{
            {
                SNS: events.SNSEntity{
                    Message: imgMock,
                },
            },
        },
    }

    err := handleRequest(ctxV, snsEventMock)
    assert.NoError(t, err)

}

Я также пробовал другие способы, такие как передача ему структуры с этими параметрами и т. Д., Но я всегда получаю false.Например, я попробовал также:

type TestMock struct {
    AwsRequestID string
    InvokedFunctionArn string
    Identity lambdacontext.CognitoIdentity
    ClientContext lambdacontext.ClientContext
}

func TestHandleRequest(t *testing.T) {

    c := context.Background()

    testMock := TestMock{
        AwsRequestID : "some_aws_id",
        InvokedFunctionArn : "some_arn",
        Identity : lambdacontext.CognitoIdentity{},
        ClientContext : lambdacontext.ClientContext{},
    }

    ctxV := context.WithValue(c, "", testMock)

    . . .

}

Я проверил источник FromContext и некоторое время чесал голову.

// LambdaContext is the set of metadata that is passed for every Invoke.
type LambdaContext struct {
    AwsRequestID       string
    InvokedFunctionArn string
    Identity           CognitoIdentity
    ClientContext      ClientContext
}

// An unexported type to be used as the key for types in this package.
// This prevents collisions with keys defined in other packages.
type key struct{}

// The key for a LambdaContext in Contexts.
// Users of this package must use lambdacontext.NewContext and 
lambdacontext.FromContext

// instead of using this key directly.
var contextKey = &key{}

// FromContext returns the LambdaContext value stored in ctx, if any.
func FromContext(ctx context.Context) (*LambdaContext, bool) {
    lc, ok := ctx.Value(contextKey).(*LambdaContext)
    return lc, ok
}

Конечно, этовозвращает false, даже если я просто передам ему context.Background().

Есть идеи, как мне построить действительный context.Context, чтобы lambdacontext.FromContext вернул true?

1 Ответ

0 голосов
/ 23 мая 2018

lambda.FromContext() проверяет, содержит ли переданный context.Context значение с удержанием «частного» ключа в пакете lambdacontext:

// An unexported type to be used as the key for types in this package.
// This prevents collisions with keys defined in other packages.
type key struct{}

// The key for a LambdaContext in Contexts.
// Users of this package must use lambdacontext.NewContext and lambdacontext.FromContext
// instead of using this key directly.
var contextKey = &key{}

// FromContext returns the LambdaContext value stored in ctx, if any.
func FromContext(ctx context.Context) (*LambdaContext, bool) {
    lc, ok := ctx.Value(contextKey).(*LambdaContext)
    return lc, ok
}

Вы не можете получить доступ к этому ключу и не можете «воспроизвести» его (вы не можете создать значение, которое будет равно этому «закрытому» ключу).

Но естьпростой способ, просто используйте lambdacontext.NewContext(), чтобы получить контекст, который будет иметь этот ключ:

// NewContext returns a new Context that carries value lc.
func NewContext(parent context.Context, lc *LambdaContext) context.Context {
    return context.WithValue(parent, contextKey, lc)
}

Итак, решение:

ctx := context.Background()
// Add keys to your liking, then:
lc := new(lambdacontext.LambdaContext)
ctx = lambdacontext.NewContext(ctx, lc)
...