【问题标题】:App Engine Cloud Endpoints Unit Testing, Issues with Data Nucleus, Is it possible?App Engine Cloud Endpoints 单元测试,Data Nucleus 的问题,可能吗?
【发布时间】:2014-02-06 18:50:10
【问题描述】:

我们已经使用 Google App Engine Cloud Endpoints 构建了一个基本的 RESTful API,并且我们希望对我们编写的一些代码进行单元测试,以检查插入和更新是否符合我们的预期。

我已经研究了 Google 提供的 Local Unit Testing documentation,并实现了它建议的所有内容,但是在调用 EntityManager.close() 时仍然会崩溃。我已经添加了 4 个 .jar 文件,并在我的测试文件中使用了 LocalServiceTestHelper

我希望有人能对这个问题有所了解,我假设我需要做的就是更改 persistance.xml 中的一个值,以允许 DataNucleus 在本地单元测试中运行,或者可能是 . jar 文件我不见了?

我希望有人可以提供帮助,Google App Engine 的众多用户之一!我可以提供代码,但我真正在做的只是EntityManager.persist(Obj); ... EntityManager.close();

与问题相关的控制台输出为:

Jan 17, 2014 12:08:04 PM org.datanucleus.transaction.Transaction rollback

SEVERE: Operation rollback failed on resource: com.google.appengine.datanucleus.DatastoreXAResource@556afa8, error code UNKNOWN and transaction: [DataNucleus Transaction, ID=Xid=, enlisted resources=[com.google.appengine.datanucleus.DatastoreXAResource@556afa8]]

指向数据核问题。堆栈跟踪

javax.persistence.PersistenceException: Illegal argument at org.datanucleus.api.jpa.NucleusJPAHelper.getJPAExceptionForNucleusException(NucleusJPAHelper.java:298) at org.datanucleus.api.jpa.JPAEntityManager.close(JPAEntityManager.java:197) at com.multipie.snapture.HashtagEndpoint.insertHashtag(HashtagEndpoint.java:124) at com.multipie.snapture.tests.HashtagTest.testInsertHashtag(HashtagTest.java:30) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at junit.framework.TestCase.runTest(TestCase.java:176) at junit.framework.TestCase.runBare(TestCase.java:141) at junit.framework.TestResult$1.protect(TestResult.java:122) at junit.framework.TestResult.runProtected(TestResult.java:142) at junit.framework.TestResult.run(TestResult.java:125) at junit.framework.TestCase.run(TestCase.java:129) at junit.framework.TestSuite.runTest(TestSuite.java:255) at junit.framework.TestSuite.run(TestSuite.java:250) at org.junit.internal.runners.JUnit38ClassRunner.run(JUnit38ClassRunner.java:84) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) Caused by: java.lang.IllegalArgumentException: transactions on multiple entity groups only allowed in High Replication applications at com.google.appengine.api.datastore.DatastoreApiHelper.translateError(DatastoreApiHelper.java:39) at com.google.appengine.api.datastore.DatastoreApiHelper$1.convertException(DatastoreApiHelper.java:76) at com.google.appengine.api.utils.FutureWrapper.get(FutureWrapper.java:94) at com.google.appengine.api.datastore.FutureHelper.getInternal(FutureHelper.java:71) at com.google.appengine.api.datastore.FutureHelper.quietGet(FutureHelper.java:32) at com.google.appengine.api.datastore.TransactionImpl.getHandle(TransactionImpl.java:97) at com.google.appengine.api.datastore.TransactionImpl.getId(TransactionImpl.java:190) at com.google.appengine.api.datastore.BaseDatastoreServiceImpl.localTxnToRemoteTxn(BaseDatastoreServiceImpl.java:130) at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl.doBatchPut(AsyncDatastoreServiceImpl.java:532) at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl.put(AsyncDatastoreServiceImpl.java:490) at com.google.appengine.api.datastore.AsyncDatastoreServiceImpl.put(AsyncDatastoreServiceImpl.java:444) at com.google.appengine.api.datastore.DatastoreServiceImpl.put(DatastoreServiceImpl.java:86) at com.google.appengine.datanucleus.WrappedDatastoreService.put(WrappedDatastoreService.java:112) at com.google.appengine.datanucleus.EntityUtils.putEntitiesIntoDatastore(EntityUtils.java:766) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObjectsInternal(DatastorePersistenceHandler.java:314) at com.google.appengine.datanucleus.DatastorePersistenceHandler.insertObject(DatastorePersistenceHandler.java:218) at org.datanucleus.state.JDOStateManager.internalMakePersistent(JDOStateManager.java:2381) at org.datanucleus.state.JDOStateManager.flush(JDOStateManager.java:3778) at org.datanucleus.ObjectManagerImpl.flushInternalWithOrdering(ObjectManagerImpl.java:3888) at org.datanucleus.ObjectManagerImpl.flushInternal(ObjectManagerImpl.java:3811) at org.datanucleus.ObjectManagerImpl.flush(ObjectManagerImpl.java:3751) at org.datanucleus.ObjectManagerImpl.preCommit(ObjectManagerImpl.java:4141) at org.datanucleus.ObjectManagerImpl.transactionPreCommit(ObjectManagerImpl.java:428) at org.datanucleus.TransactionImpl.internalPreCommit(TransactionImpl.java:398) at org.datanucleus.TransactionImpl.commit(TransactionImpl.java:287) at org.datanucleus.ObjectManagerImpl.close(ObjectManagerImpl.java:1090) at org.datanucleus.api.jpa.JPAEntityManager.close(JPAEntityManager.java:193) ... 21 more

【问题讨论】:

  • “仅在高复制应用程序中允许在多个实体组上进行事务”,所以问题出在 GAE 的数据存储区,而不是“DataNucleus”
  • 您是否设法编写了针对 Cloud Endpoints 的测试?我还没有找到任何关于为端点编写自动测试的文档。

标签: java google-app-engine unit-testing datanucleus google-cloud-endpoints


【解决方案1】:

this answer 中,数据存储操作最终保持一致的可能性为 1%,并且可能测试会失败。如果设置为 0%,LocalService 将抛出异常。有更好的解决方案。

该配置允许您设置自定义高复制策略。你可以通过设置一个策略来解决这个问题,这样你的写入将永远适用。

static final class ConsistentHighRepPolicy implements HighRepJobPolicy {
    @Override
    public boolean shouldRollForwardExistingJob(Key key) {
        return true;
    }

    @Override
    public boolean shouldApplyNewJob(Key key) {
        return true;
    }
}


Config config = new LocalDatastoreServiceTestConfig()
                       .setAlternateHighRepJobPolicyClass(ConsistentHighRepPolicy.class);

【讨论】:

    【解决方案2】:

    好的,遇到了一个帮助我的谷歌代码项目 - datanucleus-appengine-test

    设置LocalServiceTestHelper时需要在LocalDatastoreServiceTestConfig上设置一些特殊参数。代码如下:

            // Create High-Replication-Datastore simulation
            LocalDatastoreServiceTestConfig config = new LocalDatastoreServiceTestConfig();
            config.setDefaultHighRepJobPolicyUnappliedJobPercentage(1); // Can't be <1 and still have
                                                                        // multi-XG txns
            config.setStoreDelayMs(0);
            helper = new LocalServiceTestHelper(config);
            helper.setUp();
    

    【讨论】:

    • 这个答案有 1% 的几率失败。当然你可以设置一个新的随机种子并临时修复它,但不能保证它会在其他开发者的机器上工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-01-13
    • 1970-01-01
    • 1970-01-01
    • 2017-03-23
    相关资源
    最近更新 更多