1

我們已經使用Google App Engine Cloud Endpoints構建了一個基本的RESTful API,並且我們正在尋找單元測試我們編寫的一些代碼,以檢查插入和更新是否符合我們所期望的一切。App Engine雲端點單元測試,數據核問題,有可能嗎?

我查看了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: [email protected], error code UNKNOWN and transaction: [DataNucleus Transaction, ID=Xid=, enlisted resources=[[email protected]]]

指向DataNucleus將問題。堆棧跟蹤

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

+1

「在多個實體組交易只允許在高複製的應用」,所以這個問題是GAE的數據存儲,而不是與「DataNucleus將」 – DataNucleus

+0

你有沒有設法寫測試對雲終點?我還沒有發現任何有關爲端點編寫自動測試的文檔。 –

回答

0

好,碰到一個谷歌代碼項目,它幫了我 - 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(); 
+0

該答案有1%的失敗機率。當然,您可以設置一個新的隨機種子並暫時修復它,但不能保證它可以在另一個開發人員的機器上工作。 – nimcap

0

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