JUnit Test with JDO
オブジェクトの永続化の際にキーの自動生成あたりで躓いてしまい、Unit Testを書くことに。
普通に書いて動かしてみたら、
java.lang.NullPointerException: No API environment is registered for this thread. at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppId(DatastoreApiHelper.java:74) at com.google.appengine.api.datastore.DatastoreServiceImpl.beginTransaction(DatastoreServiceImpl.java:295) at org.datanucleus.store.appengine.RuntimeExceptionWrappingDatastoreService.beginTransaction(RuntimeExceptionWrappingDatastoreService.java:209) at org.datanucleus.store.appengine.jdo.DatastoreJDOTransaction.begin(DatastoreJDOTransaction.java:50) ...
と怒られてしまいました。何かスレッドコンテキストが必要らしい。確かにJDO等の初期化処理をしていないので、動かないと言われても仕方がないのかな。
ここにあるように、appengine-api-stubs.jarとappengine-local-runtime.jarをbuild pathに追加して、TestCase#setUp()で以下のコードを書いてみたものの、
@Before public void setUp(){ ApiProxy.setEnvironmentForCurrentThread(new LifecycleEnvironment()); ApiProxy.setDelegate(new ApiProxyLocalImpl(new File(".")){}); }
The type com.google.appengine.tools.development.ApiProxyLocalImpl is not visible
と怒られてしまいました。
そもそも先ほどの2つのjarファイルはeclipseのpluginsフォルダ下にあり、そこにbuild pathを通しているのですが、これが正しい方法なのか大分疑わしい…。SDKのバージョン変わったらこっちも修正するのだろうか。ApiProxyLocalImplというクラス名からして、大分アドホックな感じがしますが…。
それはそれとして、このApiProxyLocalImplというクラスは「appengine-local-runtime.jar」に含まれているようですが、スコープはパッケージローカルになっているようです。
// Compiled from ApiProxyLocalImpl.java (version 1.5 : 49.0, super bit) class com.google.appengine.tools.development.ApiProxyLocalImpl implements com.google.appengine.tools.development.ApiProxyLocal {
コンソールを見ると、何やらエラーが。
Exception in thread "main" java.lang.ExceptionInInitializerError at com.google.appengine.tools.util.Logging.initializeLogging(Logging.java:36) at com.google.appengine.tools.enhancer.Enhance.main(Enhance.java:40) Caused by: java.lang.IllegalArgumentException: Unable to find C:\eclipse\eclipse3.4SR2\plugins\com.google.appengine.eclipse.sdkbundle.1.3.3_1.3.3.v201004232023\appengine-java-sdk-1.3.3.1\lib\impl at com.google.appengine.tools.info.SdkInfo._getLibs(SdkInfo.java:67) at com.google.appengine.tools.info.SdkInfo.getLibs(SdkInfo.java:56) at com.google.appengine.tools.info.SdkImplInfo.<clinit>(SdkImplInfo.java:24) ... 2 more
これはどうもウッカリpluginsフォルダ下のappengineのSDKのフォルダ構成を変えてしまった為だったようです。適当に直したら消えました。
英語の方のページを見たところ、ApiProxyLocalImplではなくLocalServiceTestHelperというクラスが使われていたので、こっちを試してみることに。appengine-testing.jarとappengine-api-stubs.jarをbuild pathに追加して、
private final LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()); @Before public void setUp() { helper.setUp(); } @After public void tearDown() { helper.tearDown(); } @Test @Transaction public void testRegisterDailyLogAndTimeLog(){ ....
上記のように記述し、「Run JUnit Test」を実行したところ、JDOまわりも動作することを確認しました。SDKのバージョンは1.3.3.1です。
無事JUnit Testが動作したのでキーの生成の部分を確認したところ、子エンティティを作成した際に、親→子への参照を設定していなかった為、子のPKが自動で設定されなかったようです。親←子への参照は設定していたのですが、それだけだと子のキーの生成は行われませんでした。親→子の設定を行い、キーが生成されることを確認しました。