dounai1986 2018-05-21 14:36
浏览 40
已采纳

是否可以在不更改参数的情况下对使用AWS开发工具包的Go函数进行单元测试?

I am new to Go and have written a function that uses the AWS Secrets Manager to fetch a secret:

//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
    }

    ...
}

I need to create a unit test for the function, and to do so I need to mock the AWS Secrets Manager. I discovered a Secrets Manager Interface that AWS was created to help with unit testing. In the example displayed, the AWS Secrets Manager is passed into the function being tested, making it easy to pass in the mock service. Is this the only way to successfully unit test the function? Or can the service be mocked in the function I have above?

  • 写回答

1条回答 默认 最新

  • dongpian2559 2018-05-21 18:29
    关注

    As the comments say, make the function call a method, and take advantage of the interface AWS is providing.

    I would create a service, like this one:

    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 ...
    }
    

    That way in the tests, I could pass any mock into SecretService, like this:

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

    One caveat, I guess is that the mock has to implement all methods of SecretsManagerAPI, which I think it's a lot of work for this simple scenario... in any case you can create your own interface inside the service package with only the subset of methods you'll use, let's say you're only going to use GetSecretValueRequest, and CreateSecret:

    package service
    
    type SecretProvider interface {
        CreateSecret(*secretsmanager.CreateSecretInput) (*secretsmanager.CreateSecretOutput, error)
        GetSecretValueRequest(*secretsmanager.GetSecretValueInput) (*request.Request, *secretsmanager.GetSecretValueOutput)
    }
    

    Change the service:

    type SecretService struct {
        AwsProvider SecretProvider
    }
    

    Now your mock only has to implement SecretProvider interface methods only. And of course, AWS SecretsManager implicitly impleements SecretProvider.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 CSS实现渐隐虚线边框
  • ¥15 thinkphp6配合social login单点登录问题
  • ¥15 HFSS 中的 H 场图与 MATLAB 中绘制的 B1 场 部分对应不上
  • ¥15 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题