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

时间:2011-01-22 12:57:18

标签: spring google-app-engine automated-tests acceptance-testing

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

dao.add(entity)

我得到了可怕的“没有为此线程注册API环境。”

Caused by: java.lang.NullPointerException: No API environment is registered for this thread.
 at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppId(DatastoreApiHelper.java:108)
 at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppIdNamespace(DatastoreApiHelper.java:118)
    ....

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

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

3 个答案:

答案 0 :(得分:3)

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

然后,您可以配置dev数据存储区是写入磁盘还是仅保存在内存中(以便更快地进行测试)。如果您希望此数据与开发服务器位于同一位置,您可能需要调整此值,因为我认为默认值是“内存中”选项。如果查看javadoc,可以使用“setBackingStoreLocation”方法指向您想要的任何文件。

答案 1 :(得分:0)

我找到了解决方案!!!!

由于某种原因,测试数据存储区的Namespace,AppID和AuthDomain字段必须与dev_server的字段匹配,然后dev_server可以看到测试插入的实体。

您可以使用以下语句查看环境的值(dev_server或测试代码)

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");

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

答案 2 :(得分:0)

我找到了一种解决方法,虽然它不是很好,因为每个测试方法都不会清理数据存储区,如文章Local Unit Testing for Java中所述,但是,每次测试类都是数据存储区时,数据存储区都会开始清理如果您对此非常小心,那就不会那么糟糕。

问题是,当使用SpringJUnit4ClassRunner时,弹簧环境是在运行@Before注释之前创建的,解决方案是使用@BeforeClass并使用静态变量LocalServiceTestHelper 1}},在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();
    }

如果有人有更好的解决方案,我会很高兴听到!