如何从Gcloud beta模拟器firestore中删除所有文档?

时间:2019-11-13 21:47:10

标签: go google-cloud-firestore gcloud

我正在创建一些简单的应用程序来学习Firestore。

我通过以下方式启动了本地Firestore模拟器:

$ gcloud beta仿真器firestore启动

启动模拟器后,我使用“ go test”进行测试

我在Firestore中填充了数据,并创建了一个函数来查询添加的某些记录/文档。

我从我的应用程序中删除了一些文档,但是它们继续显示在查询中。

我尝试过:

  • 以ctrl-c和ctrl d停止

  • $ gcloud beta仿真器firestore停止

  • 重新启动了Macbook,但文档仍然存在。

我不了解重新启动计算机后数据存储的持久性,我猜测数据存储在JSON文件或类似的文件中。

我进行了搜索,但无法在模拟器上找到任何文档。

我应该启动仿真器,然后针对仿真的Firestore运行测试吗?

如何冲洗Firestore?

3 个答案:

答案 0 :(得分:2)

模拟器支持终结点来清除数据库(docs):

curl -v -X DELETE "http://localhost:PORT/emulator/v1/projects/PROJECT_NAME/databases/(default)/documents"

填写PORTPROJECT_NAME

答案 1 :(得分:1)

您可以使用此:

module.exports.teardown = async () => {
  Promise.all(firebase.apps().map(app => app.delete()));
};

现在,每次调用teardown时,您将从Firestore模拟器中删除所有数据。

答案 2 :(得分:1)

由于您使用的是 Go,这里有一个我实现的小测试助手,它有助于启动模拟器、等待它出现、清除现有数据、初始化客户端以及在完成后关闭操作符。< /p>

它使用了 Juan 答案中的技巧(您应该将其标记为答案)。

要使用此实用程序,您只需说:

client := startFirestoreEmulator(t)

源代码:

// Copyright 2021 Ahmet Alp Balkan
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Package firestoretestutil contains test utilities for starting a firestore
// emulator locally for unit tests.
package firestoretestutil

import (
    "bytes"
    "context"
    "fmt"
    "net"
    "net/http"
    "os"
    "os/exec"
    "sync"
    "testing"
    "time"

    firestore "cloud.google.com/go/firestore"
)

const firestoreEmulatorProj = "dummy-emulator-firestore-project"

// cBuffer is a buffer safe for concurrent use.
type cBuffer struct {
    b bytes.Buffer
    sync.Mutex
}

func (c *cBuffer) Write(p []byte) (n int, err error) {
    c.Lock()
    defer c.Unlock()
    return c.b.Write(p)
}

func StartEmulator(t *testing.T, ctx context.Context) *firestore.Client {
    t.Helper()
    port := "8010"
    addr := "localhost:" + port
    ctx, cancel := context.WithCancel(ctx)
    t.Cleanup(func() {
        t.Log("shutting down firestore operator")
        cancel()
    })

    // TODO investigate why there are still java processes hanging around
    // despite we kill the exec'd command, suspecting /bin/bash wrapper that gcloud
    // applies around the java process.
    cmd := exec.CommandContext(ctx, "gcloud", "beta", "emulators", "firestore", "start", "--host-port="+addr)
    out := &cBuffer{b: bytes.Buffer{}}
    cmd.Stderr, cmd.Stdout = out, out
    if err := cmd.Start(); err != nil {
        t.Fatalf("failed to start firestore emulator: %v -- out:%s", err, out.b.String())
    }
    dialCtx, clean := context.WithTimeout(ctx, time.Second*10)
    defer clean()
    var connected bool
    for !connected {
        select {
        case <-dialCtx.Done():
            t.Fatalf("emulator did not come up timely: %v -- output: %s", dialCtx.Err(), out.b.String())
        default:
            c, err := (&net.Dialer{Timeout: time.Millisecond * 200}).DialContext(ctx, "tcp", addr)
            if err == nil {
                c.Close()
                t.Log("firestore emulator started")
                connected = true
                break
            }
            time.Sleep(time.Millisecond * 200) //before retrying
        }
    }
    os.Setenv("FIRESTORE_EMULATOR_HOST", addr)
    cl, err := firestore.NewClient(ctx, firestoreEmulatorProj)
    if err != nil {
        t.Fatal(err)
    }
    os.Unsetenv("FIRESTORE_EMULATOR_HOST")
    truncateDB(t, addr)
    return cl
}

func truncateDB(t *testing.T, addr string) {
    t.Helper()
    // technique adopted from https://stackoverflow.com/a/58866194/54929
    req, _ := http.NewRequest(http.MethodDelete, fmt.Sprintf("http://%s/emulator/v1/projects/%s/databases/(default)/documents",
        addr, firestoreEmulatorProj), nil)
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        t.Fatal(err)
    }
    if resp.StatusCode != http.StatusOK {
        t.Fatalf("failed to clear db: %v", resp.Status)
    }
}