Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/amazon-web-services/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Amazon web services 是否可以在不更改参数的情况下对使用AWS SDK的Go函数进行单元测试?_Amazon Web Services_Unit Testing_Go_Mocking - Fatal编程技术网

Amazon web services 是否可以在不更改参数的情况下对使用AWS SDK的Go函数进行单元测试?

Amazon web services 是否可以在不更改参数的情况下对使用AWS SDK的Go函数进行单元测试?,amazon-web-services,unit-testing,go,mocking,Amazon Web Services,Unit Testing,Go,Mocking,我是新手,编写了一个使用AWS机密管理器获取机密的函数: //Helper function to get secret from AWS Secret Manager func getAWSSecrets() (secretMap map[string]string, err error) { // Create new AWS session in order to get db info from SecretsManager sess, err := session.Ne

我是新手,编写了一个使用AWS机密管理器获取机密的函数:

//Helper function to get secret from AWS Secret Manager
func getAWSSecrets() (secretMap map[string]string, err error) {
    // Create new AWS session in order to get db info from SecretsManager
    sess, err := session.NewSession()
    if err != nil {
        return nil, err
    }

    // Create a new instance of the SecretsManager client with session
    svc := secretsmanager.New(sess)

    //Get secret config values
    req, resp := svc.GetSecretValueRequest(&secretsmanager.GetSecretValueInput{
        SecretId: aws.String("my/secret/string"),
    })

    err = req.Send()
    if err != nil {
        return nil, err
    }

    ...
}

我需要为函数创建一个单元测试,为此我需要模拟AWS机密管理器。我发现了一个秘密。在显示的示例中,AWS Secrets Manager被传递到正在测试的函数中,这使得在模拟服务中很容易传递。这是成功单元测试功能的唯一方法吗?或者可以在我上面的函数中模拟服务

正如评论所说,让函数调用成为一种方法,并利用AWS提供的接口

我会创建一个服务,就像这样:

package service

type SecretService struct {
    AwsProvider aws.SecretsManagerAPI
}

func NewSecretService() (*SecretService, err) {
    // Create new AWS session in order to get db info from SecretsManager
    sess, err := session.NewSession()
    if err != nil {
        return nil, err
    }

    return &SecretService{
        AwsProvider: secretsmanager.New(sess),
    }, nil
}

func (s *SecretService) GetAWSSecrets() {
    req, resp := s.AwsProvider.GetSecretValueRequest(&secretsmanager.GetSecretValueInput{
        SecretId: aws.String("my/secret/string"),
    })

    err = req.Send()
    if err != nil {
        return nil, err
    }

    // More magic below ...
}
这样,在测试中,我可以将任何模拟传递到SecretService,如下所示:

func TestSecretService_GetAWSSecrets(t *testing.T) {
  service := &service.SecretService{
    AwsProvider: <use your mock here>
  }
}
更改服务:

type SecretService struct {
    AwsProvider SecretProvider
}

现在,您的mock只需实现SecretProvider接口方法。当然,AWS SecretsManager隐式地暗示了SecretProvider。

如果您确实被限制不更改参数,则必须使用全局变量占位符模拟它。这是丑陋的,因为全局变量是丑陋的。如果您可以更灵活一点,例如,通过将
getAWSSecrets()
设置为方法而不是函数,您将有很多更吸引人的选项。@Flimzy您认为将会话和机密管理器实例的创建移到主函数中,并更改函数以将机密管理器作为参数(如AWS示例中的参数)或更改
getAWSSecrets()是否更有意义
将函数转换为方法?如果您有这种灵活性,那么您就可以灵活地更改参数,从而正确地执行操作。:)您的实际约束是什么促使您说“不更改参数”@Flimzy我可以更改参数如果这是最好的方法,那么将与机密管理器相关的所有代码包装在
getAWSSecrets()中似乎是有意义的
函数。重构函数以接受
SecretsManagerAPI
参数将是使此函数可模拟的最简单方法。由于这是一种接口类型,模拟它变得很简单,并且从
secretsmanager.New()
返回的结构满足该接口,因此您可以将其传递到重构版本的
getAWSSecrets()
,而无需修改以供生产使用。
type SecretService struct {
    AwsProvider SecretProvider
}