Spring 验收测试将数据预加载到GAE dev服务器数据存储中

Spring 验收测试将数据预加载到GAE dev服务器数据存储中,spring,google-app-engine,automated-tests,acceptance-testing,Spring,Google App Engine,Automated Tests,Acceptance Testing,在我的应用程序中,我将一组DAO注入到我的应用程序层中。对于我正在编写的验收测试,我想用数据预加载dev_服务器数据存储,因此我在JUnit测试中使用相同的Spring配置(使用@ContextConfiguration注释)将相关DAO的实例注入到测试中。当我实际去存储一些数据时,例如: dao.add(entity) 我得到了可怕的“没有为这个线程注册API环境” 这可能是因为我的测试用例没有在GAE application-web.xml中读取应用程序的详细信息(尽管我在这里猜测我可能真

在我的应用程序中,我将一组DAO注入到我的应用程序层中。对于我正在编写的验收测试,我想用数据预加载dev_服务器数据存储,因此我在JUnit测试中使用相同的Spring配置(使用@ContextConfiguration注释)将相关DAO的实例注入到测试中。当我实际去存储一些数据时,例如:

dao.add(entity)
我得到了可怕的“没有为这个线程注册API环境”

这可能是因为我的测试用例没有在GAE application-web.xml中读取应用程序的详细信息(尽管我在这里猜测我可能真的错了);因此,它不知道如何写入dev_服务器上运行的应用程序正在读取/写入的同一数据存储

如何让我的测试“指向”与应用程序相同的数据存储?是否有一些“数据源”机制可以同时注入到应用程序和测试中?有没有办法让我的测试强制数据存储api读取所需的配置?

是一个讨论如何进行连接到dev数据存储的单元测试的页面。这就是你要找的东西吗?基本上,它讨论了两个类,LocalServiceTestHelper和LocalDatastoreServiceTestConfig,您可以使用它们来设置测试环境。虽然给出的示例用于单元测试,但我相信它也适用于您的情况


然后,您可以配置诸如是将dev数据存储写入磁盘还是仅保存在内存中(以进行更快的测试)之类的内容。如果您想让这些数据与您的dev服务器放在同一个位置,您可能需要对其进行调整,因为我认为默认设置是“内存中”选项。如果您查看,有一个“setBackingStoreLocation”方法,您可以指向您想要的任何文件。

我找到了解决方案

出于某种原因,测试数据存储的名称空间、AppID和AuthDomain字段必须与dev_服务器的字段匹配,然后dev_服务器可以看到测试插入的实体

您可以通过以下语句查看环境(dev_服务器或测试代码)的值

System.out.println(NamespaceManager.get());
System.out.println(ApiProxy.getCurrentEnvironment().getAppId());
System.out.println(ApiProxy.getCurrentEnvironment().getAuthDomain());
在LocalServiceTestHelper实例(例如:gaeHelper)中,可以为测试环境设置值

// the NamespaceManager is thread local.
NamespaceManager.set(NamespaceManager.getGoogleAppsNamespace());
gaeHelper.setEnvAppId(<the name of your app in appengine-web.xml>);
gaeHelper.setEnvAuthDomain("gmail.com");
//名称空间管理器是线程本地的。
NamespaceManager.set(NamespaceManager.getGoogleAppsNamespace());
gaeHelper.setEnvAppId();
gaeHelper.setEnvAuthDomain(“gmail.com”);

然后dev_服务器将看到您的实体。但是,由于同步问题,如果测试在dev_服务器启动后写入数据存储,dev_服务器将看不到它,除非可以强制它重新读取文件(我还没有弄清楚)。否则服务器必须重新启动。

我找到了一个解决方法,尽管它不是很好,因为每个测试方法都不会清理数据存储,正如本文中所解释的,但是,每次运行测试类时,数据存储都会开始清理,所以如果您小心的话,情况并不是那么糟糕

问题是,当使用
SpringJUnit4ClassRunner
时,spring环境是在运行
@before
注释之前创建的,解决方案是使用
@BeforeClass
并为
LocalServiceTestHelper
使用静态变量,以便在spring环境设置之前创建它们

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:META-INF/spring/context-test.xml")
@Transactional
public class MyTest {


    @Inject
    private MyService myService;

    private static final LocalServiceTestHelper helper = 
        new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

    @BeforeClass
    public static void beforeClass() {
        helper.setUp();
    }

    @AfterClass
    public static void afterClass() {
        helper.tearDown();
    }

如果有人有更好的解决办法,我很高兴听到

我尝试在测试中将数据存储备份存储(使用LocalDatastoreServiceTestConfig)设置为dev_服务器写入的同一文件(例如:WEB-INF/appengine generated/local_db.bin),测试将实体成功写入该文件。但是,当我启动dev_uu服务器并查看管理控制台时,测试中写入的实体不会出现。如果我运行另一个查询数据存储的测试(使用LocalDatastoreServiceTestConfig),就会找到实体。实体最终出现在数据存储中,但在dev_服务器上运行的应用程序看不到它。我认为这与dev_服务器和LocalServiceTestHelper将实体放入的命名空间有关,这导致应用程序看不到测试实体。阅读本文时,我尝试将测试代码中的实体放入应用程序所使用的空(“”)命名空间中,但应用程序仍然无法看到它们。为了清楚起见,我使用NamespaceManager.set()方法更改开发服务器代码和测试代码中的命名空间。我也试过用不同的字符串,但也没用。哇。真烦人。必须有一种方法来实现你想要的。。。我们需要一个“nick的标志”按钮。不幸的是,这种方法只适用于GAE<1.4.2(我使用的是1.4.0)。API中的某些内容在使此解决方案无效的版本之间必须发生更改。
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("classpath:META-INF/spring/context-test.xml")
@Transactional
public class MyTest {


    @Inject
    private MyService myService;

    private static final LocalServiceTestHelper helper = 
        new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig());

    @BeforeClass
    public static void beforeClass() {
        helper.setUp();
    }

    @AfterClass
    public static void afterClass() {
        helper.tearDown();
    }