当返回未引用的struct属性而不是struct时,单元测试会出现panic



如何测试返回字符串或数字类型的结构属性而不是结构本身的函数?

我正在尝试用Test Code块测试Lambda Code块。

Lambda Code块下面,我返回* resps . userpoolclient。ClientSecret,它指向string,而不是*string

当我运行测试时,我相信我得到一个恐慌错误,因为*resp.UserPoolClient.ClientSecret在调试器中是nil

返回去引用属性是错误的方法吗?想知道我是否最好只是返回整个respp对象,而不是取消引用?我这样做是因为我根本不需要修改值,只需要副本可供参考。

<<p>λ代码/strong>
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
}
<<p>测试代码/strong>
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")
}
})
}

返回去引用属性是错误的方法吗?

就我个人而言,我不认为这是错的。我也会这么做。但是更有经验的Go开发人员可能能够在这里提供更细微和详细的答案。

关于恐慌,我认为问题是您创建的mock没有返回所有必需的信息。

你的模拟:

idpMock := mockDescribeUserPoolClient{
Response: &cidp.DescribeUserPoolClientOutput{},
Error:    nil,
}

你只创建一个"空"DescribeUserPoolClientOutput的实例。但是您想要测试的代码确实访问了两个您没有定义的子节点:

  1. UserPoolClient(struct reference)
  2. ClientSecret(string reference)
  3. 代码:

*resp.UserPoolClient.ClientSecret

所以你的mock也需要mock这些

idpMock := mockDescribeUserPoolClient{
Response: &cidp.DescribeUserPoolClientOutput{
UserPoolClient: &cidp.UserPoolClientType{
ClientSecret: aws.String("example-secret")
}
},
Error:    nil,
}

这应该能消除你的恐慌。

最新更新