java - 使用 Java 的 Google 数据存储模拟器(不使用 GAE)

标签 java emulation google-cloud-datastore

我正在使用 Google Cloud 的 Java 数据存储客户端库来访问云数据存储。

备注 :我没有使用 App Engine 来部署我的应用程序;只是出于开发目的运行本地应用程序。

按照示例,我可以读取/写入 Cloud Datastore。

Datastore datastore = DatastoreOptions.defaultInstance().service();
KeyFactory keyFactory = datastore.newKeyFactory().setKind("MyKind");
Key key = keyFactory.newKey();
Entity entity = datastore.get(key);

我希望能够写入本地数据存储模拟器实例。
跟随指南 here , 我跑 gcloud beta emulators datastore start .
这显示在我的终端中:
C:\Users\User>gcloud beta emulators datastore start
WARNING: Reusing existing data in [C:\Users\User\AppData\Roaming\gcloud\emulators\datastore].
Executing: cmd /c C:\Users\User\AppData\Local\Google\Cloud SDK\google-cloud-sdk\platform\cloud-datastore-emulator\cloud_datastore_emulator.cmd start --host=localhost --port=8964 --store_on_disk=True --consistency=0.9 --allow_remote_shutdown C:\Users\User\AppData\Roaming\gcloud\emulators\datastore
[datastore] Oct 31, 2016 11:37:27 AM com.google.cloud.datastore.emulator.CloudDatastore$FakeDatastoreAction$7 apply
[datastore] INFO: Provided --allow_remote_shutdown to start command which is no longer necessary.
[datastore] Oct 31, 2016 11:37:27 AM com.google.cloud.datastore.emulator.impl.LocalDatastoreFileStub <init>
[datastore] INFO: Local Datastore initialized:
[datastore]     Type: High Replication
[datastore]     Storage: C:\Users\User\AppData\Roaming\gcloud\emulators\datastore\WEB-INF\appengine-generated\local_db.bin
[datastore] Oct 31, 2016 11:37:28 AM io.grpc.internal.ManagedChannelImpl <init>
[datastore] INFO: [ManagedChannelImpl@5e955596] Created with target localhost:8964
[datastore] Oct 31, 2016 11:37:28 AM com.google.cloud.datastore.emulator.impl.LocalDatastoreFileStub load
[datastore] INFO: The backing store, C:\Users\User\AppData\Roaming\gcloud\emulators\datastore\WEB-INF\appengine-generated\local_db.bin, does not exist. It will be created.
[datastore] Oct 31, 2016 11:37:28 AM io.gapi.emulators.netty.NettyUtil applyJava7LongHostnameWorkaround
[datastore] INFO: Unable to apply Java 7 long hostname workaround.
[datastore] API endpoint: http://localhost:8964
[datastore] If you are using a library that supports the DATASTORE_EMULATOR_HOST environment variable, run:
[datastore]
[datastore]   export DATASTORE_EMULATOR_HOST=localhost:8964
[datastore]
[datastore] Dev App Server is now running.
[datastore]

我打开另一个终端并设置环境变量:
C:\Users\User>gcloud beta emulators datastore env-init > set_vars.cmd && set_vars.cmd
C:\Users\User>set DATASTORE_DATASET=my-project-id
C:\Users\User>set DATASTORE_EMULATOR_HOST=localhost:8964
C:\Users\User>set DATASTORE_EMULATOR_HOST_PATH=localhost:8964/datastore
C:\Users\User>set DATASTORE_HOST=http://localhost:8964
C:\Users\User>set DATASTORE_PROJECT_ID=my-project-id

我运行我的应用程序并进行 REST 调用以发布或检索实体,但这仅读取/写入云数据存储。前往 localhost:8964/datastore给我 Not Found .虽然启动模拟器告诉我它创建了 local_db.bin文件,据说包含它的文件夹是空的。
我还想避免使用 LocalDatastoreHelper 来访问本地模拟器。有什么办法可以只使用 gcloud 来实现吗?

最佳答案

我假设您想针对 Datastore Emulator 进行测试。在这种情况下,无需从 shell 启动数据存储模拟器。有一个LocalDatastoreHelper在 gcloud 库中,可让您轻松创建、启动、重置和停止本地数据存储模拟器。

我没有找到任何关于它的文档,所以我为你创建了这个测试用例:

import com.google.cloud.datastore.Datastore;
import com.google.cloud.datastore.DatastoreOptions;
import com.google.cloud.datastore.Entity;
import com.google.cloud.datastore.KeyFactory;
import com.google.cloud.datastore.testing.LocalDatastoreHelper;
import org.junit.*;

import java.io.IOException;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;

/**
 * This testcase demonstrate the use of the datastore emulator in JUnit test cases.
 *
 * from @link https://www.kontaktlinsen-preisvergleich.de
 */
public class DatastoreEmulatorTest {

    protected static LocalDatastoreHelper localDatastoreHelper;

    protected Datastore datastore;

    protected KeyFactory keyFactory;

    @BeforeClass
    public static void setUpClass() throws InterruptedException, IOException {
        // create and start a local datastore emulator on a random free port
        // this also means that you probably can run tests like this concurrently.
        System.out.println("[Datastore-Emulator] start");
        localDatastoreHelper = LocalDatastoreHelper.create();
        localDatastoreHelper.start();
        System.out.println("[Datastore-Emulator] listening on port: " + localDatastoreHelper.getPort());

        // set the system property to tell the gcloud lib to use the datastore emulator
        System.setProperty("DATASTORE_EMULATOR_HOST","localhost:" + localDatastoreHelper.getPort());
    }

    @Before
    public void setUp() {
        // create the datastore instance
        // because of the system property set it in setUpClass() this
        // datastore will be connected with the datastore emulator.
        datastore = DatastoreOptions.getDefaultInstance().getService();
        keyFactory = datastore.newKeyFactory().setKind("TestEntity");
    }

    @After
    public void tearDown() throws IOException {
        System.out.println("[Datastore-Emulator] reset");
        // this resets the datastore after every test
        localDatastoreHelper.reset();
    }

    @AfterClass
    public static void tearDownClass() throws InterruptedException, IOException {
        System.out.println("[Datastore-Emulator] stop");
        // this stops the datastore emulator after all tests are done
        localDatastoreHelper.stop();
    }

    @Test
    public void test1() {
        // stores an entity in the datastore and retrieves it later

        // create an Entity "TestEntity"
        Entity.Builder builder = Entity.newBuilder(keyFactory.newKey(42));
        builder.set("name", "Test1");

        // store it in datastore
        datastore.put(builder.build());

        // retrieve entity by key
        Entity entity = datastore.get(keyFactory.newKey(42));
        assertNotNull(entity);
        assertEquals("Test1", entity.getString("name"));
    }

    @Test
    public void test2() {
        // try to access the entity created in test1, shouldn't work because
        // of calling reset in tearDown() after each test.

        // try to retrieve entity by key
        Entity entity = datastore.get(keyFactory.newKey(42));
        assertNull(entity);
    }
}

LocalDatastoreHelper 在空闲端口上创建一个 Datastore Emulator 实例并且不存储到磁盘 - 当您使用调试器停止测试用例并查找进程时,您会发现如下内容:
$ ps ax | grep CloudDatastore
2614   ??  R      0:01.39 /usr/bin/java -cp /Users/marco/google-cloud-sdk/platform/cloud-datastore-emulator/CloudDatastore.jar com.google.cloud.datastore.emulator.CloudDatastore /Users/marco/google-cloud-sdk/platform/cloud-datastore-emulator/cloud_datastore_emulator start --host=localhost --port=57640 --store_on_disk=False --consistency=0.9 --allow_remote_shutdown /var/folders/ky/c126qk_161159ltyrbpdxv8w0000gn/T/gcd2141205756617995044

这也意味着您也应该能够并行运行测试。

关于java - 使用 Java 的 Google 数据存储模拟器(不使用 GAE),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40348653/

相关文章:

java - 动态实例化新类并将其转换回 Fragment 类型

java - 无法跳过某项 Activity

android - 在模拟器 2.2 中安装 android 市场应用程序

CUDA:cudaMemcpy 仅在仿真模式下工作

java - GAE w/Objectify - 你能查询 HashMap 吗?

java - GAE 远程 API - 无法连接

google-cloud-datastore - Google Cloud Datastore 是否支持计数器等原子操作?

java - 在一个正方形内生成 N 个点(均匀)

java - 多线程——MySQL java connector prepared statement使用

android - Facebook android native 应用程序无法在实际设备上运行