如何在golang中对google云存储进行单元测试?

Jes*_*der 10 google-app-engine unit-testing go google-cloud-storage

我正在Go中编写一个使用Google云存储的appengine应用程序.

例如,我的"阅读"代码如下所示:

client, err := storage.NewClient(ctx)
if err != nil {
    return nil, err
}
defer func() {
    if err := client.Close(); err != nil {
        panic(err)
    }
}()
r, err := client.Bucket(BucketName).Object(id).NewReader(ctx)
if err != nil {
    return nil, err
}
defer r.Close()
return ioutil.ReadAll(r)
Run Code Online (Sandbox Code Playgroud)

...... ctx来自appengine的背景在哪里.

当我在单元测试(使用aetest)中运行此代码时,它实际上将请求发送到我的云存储; 我想密封地运行它,类似于aetest允许伪数据存储调用的方式.

(可能是相关问题,但它处理python,链接的github问题表明它是以特定于python的方式解决的).

我怎样才能做到这一点?

bos*_*ood 7

此处还建议的一种方法是允许您的 GCS 客户端在单元测试时将其下载器替换为存根。首先,定义一个与您使用 Google Cloud Storage 库的方式相匹配的接口,然后在您的单元测试中使用假数据重新实现它。

像这样的东西:

type StorageClient interface {
  Bucket(string) Bucket  // ... and so on, matching the Google library
}

type Storage struct {
  client StorageClient
}

// New creates a new Storage client
// This is the function you use in your app
func New() Storage {
  return NewWithClient(&realGoogleClient{}) // provide real implementation here as argument
}

// NewWithClient creates a new Storage client with a custom implementation
// This is the function you use in your unit tests
func NewWithClient(client StorageClient) {
  return Storage{
    client: client,
  }
}
Run Code Online (Sandbox Code Playgroud)

它可以是很多样板来模拟整个第三方的API,所以也许你就可以通过生成一些与嘲笑,使其更容易golang /模拟嘲弄


小智 7

我做过这样的事情......

由于存储客户端正在发送 HTTPS 请求,因此我使用以下命令模拟了 HTTPS 服务器httptest

func Test_StorageClient(t *testing.T) {
    tests := []struct {
        name        string
        mockHandler func() http.Handler
        wantErr     bool
    }{
        {
            name: "test1",
            mockHandler: func() http.Handler {
                return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                    w.Write([]byte("22\n96\n120\n"))
                    return
                })
            },
            wantErr: false,
        },
        {
            name: "test2 ",
            mockHandler: func() http.Handler {
                return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
                    w.WriteHeader(http.StatusNotFound)
                    return
                })
            },
            wantErr: true,
        },
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            serv := httptest.NewTLSServer(tt.mockHandler())
            httpclient := http.Client{
                Transport: &http.Transport{
                    TLSClientConfig: &tls.Config{
                        InsecureSkipVerify: true,
                    },
                },
            }
            client, _ := storage.NewClient(context.Background(), option.WithEndpoint(serv.URL), option.WithoutAuthentication(), option.WithHTTPClient(&httpclient))
            got, err := readFileFromGCS(client)
            if (err != nil) != tt.wantErr {
                t.Errorf("error = %v, wantErr %v", err, tt.wantErr)
                return
            }
        })
    }
}
Run Code Online (Sandbox Code Playgroud)


Ada*_*dam 1

Python 开发服务器上的云存储是使用本地文件和 Blobstore 服务进行模拟的,这就是使用带有测试床(也是特定于 Python)的 Blobstore 存根的解决方案有效的原因。但是,Go 运行时上的 Cloud Storage 没有此类本地模拟。

正如 Sachin 所建议的,对 Cloud Storage 进行单元测试的方法是使用模拟。这是在内部和其他运行时(例如node )上完成的方式。