Amazon web services 是否可以在不更改参数的情况下对使用AWS SDK的Go函数进行单元测试?
我是新手,编写了一个使用AWS机密管理器获取机密的函数: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
//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
}