问题
How does one go about testing a function that is returning a struct attribute that is of type string or number, rather than the struct itself?
I am trying to test the Lambda Code
block with the Test Code
block.
In Lambda Code
block below, I am returning *resp.UserPoolClient.ClientSecret which dereferences to a string
, rather than the *string
.
When I run my test, I believe I get a panic error as *resp.UserPoolClient.ClientSecret
is nil
in the debugger.
Is my returning of the de-referenced attribute the wrong approach? Wondering if I'm better off just returning the whole resp object, not de-referenced? I was doing it this way as I didn't need to modify the values at all, just needed copies available for reference.
Lambda Code
package main
import (
"fmt"
"log"
"os"
"github.com/aws/aws-sdk-go/aws"
"github.com/aws/aws-sdk-go/aws/awserr"
"github.com/aws/aws-lambda-go/lambda"
"github.com/aws/aws-sdk-go/aws/session"
cidp "github.com/aws/aws-sdk-go/service/cognitoidentityprovider"
cidpif "github.com/aws/aws-sdk-go/service/cognitoidentityprovider/cognitoidentityprovideriface"
util "github.com/sean/repo/internal/util"
)
type application struct {
config configuration
}
type configuration struct {
ClientPoolID string
UserPoolID string
idp cidpif.CognitoIdentityProviderAPI
}
func (app application) getUserPoolClientSecret() (string, error) {
input := &cidp.DescribeUserPoolClientInput{
UserPoolId: aws.String(app.config.UserPoolID),
ClientId: aws.String(app.config.ClientPoolID),
}
resp, err := app.config.idp.DescribeUserPoolClient(input)
if err != nil {
if aerr, ok := err.(awserr.Error); ok {
log.Printf("[ERROR] %v", aerr.Error())
} else {
log.Printf("[ERROR] %v", err.Error())
}
return "", err
}
log.Println("[INFO] Obtained user pool client secret successfully")
return *resp.UserPoolClient.ClientSecret, nil
}
// omitted for brevity
func main() {
config := configuration{
ClientPoolID: os.Getenv("CLIENT_POOL_ID"),
UserPoolID: os.Getenv("USER_POOL_ID"),
idp: cidp.New(session.Must(session.NewSession())),
}
app := application{config: config}
lambda.Start(app.handler) // handler() calls app.getUserPoolClientSecret
}
Test Code
package main
import (
"testing"
cidp "github.com/aws/aws-sdk-go/service/cognitoidentityprovider"
cidpif "github.com/aws/aws-sdk-go/service/cognitoidentityprovider/cognitoidentityprovideriface"
)
type mockDescribeUserPoolClient struct {
cidpif.CognitoIdentityProviderAPI
Response *cidp.DescribeUserPoolClientOutput
Error error
}
func (m mockDescribeUserPoolClient) DescribeUserPoolClient(*cidp.DescribeUserPoolClientInput) (*cidp.DescribeUserPoolClientOutput, error) {
return m.Response, nil
}
func TestGetUserPoolClientSecret(t *testing.T) {
t.Run("Successfully obtained client pool secret", func(t *testing.T) {
idpMock := mockDescribeUserPoolClient{
Response: &cidp.DescribeUserPoolClientOutput{},
Error: nil,
}
app := application{config: configuration{
ClientPoolID: "test",
UserPoolID: "test",
idp: idpMock,
}}
_, err := app.getUserPoolClientSecret()
if err != nil {
t.Fatal("App secret should have been obtained")
}
})
}
回答1:
Is my returning of the de-referenced attribute the wrong approach?
Personally, I don't think it is wrong. I would do the same. But more seasoned Go developers might be able to contribute a more nuanced and detailed answer here.
In regards to the panic, I think the issue is that the mock you create does not return all the required information.
Your mock:
idpMock := mockDescribeUserPoolClient{
Response: &cidp.DescribeUserPoolClientOutput{},
Error: nil,
}
You only create an "empty" instance of DescribeUserPoolClientOutput
. But the code that you want to test does access two children, that you did not define:
UserPoolClient
(struct reference)ClientSecret
(string reference)
Your code:
*resp.UserPoolClient.ClientSecret
So your mock needs to mock those as well:
idpMock := mockDescribeUserPoolClient{
Response: &cidp.DescribeUserPoolClientOutput{
UserPoolClient: &cidp.UserPoolClientType{
ClientSecret: aws.String("example-secret")
}
},
Error: nil,
}
That should fix your panic.
来源:https://stackoverflow.com/questions/65767851/unit-tests-panic-when-returning-dereferenced-struct-attribute-rather-than-struct