GAE/Jでデータストアの単体テスト

GAEはじめました。とりあえず、BigTableを試してみるべくJDOを使った単体テストに挑戦!
ローカル サービスの実装でのユニットのテストの通りに進めればデータを保存できる模様。


EclipseのGAEプラグインからプロジェクトを作成した場合はappengine-api-stubs.jar および appengine-local-runtime.jarがないはずなので、ここからJavaSDKを落としてきてクラスパスを通す必要がある。

データストアとJDOの使用にあるGreetingをテストしてみる。

public class GreetingTest {

	PersistenceManager pm;
	
	@Before
	public void setUp() throws Exception {
		ApiProxy.setEnvironmentForCurrentThread(new TestEnvironment());
		ApiProxy.setDelegate(new ApiProxyLocalImpl(new File(".")){});
		((ApiProxyLocalImpl)ApiProxy.getDelegate()).setProperty(LocalDatastoreService.NO_STORAGE_PROPERTY, Boolean.TRUE.toString());
		pm = JDOHelper.getPersistenceManagerFactory("transactions-optional").getPersistenceManager();
	}
	
	@Test
	public void test() throws Exception {
                Greeting g = new Greeting("a", new Date());
		pm.makePersistent(g);
		System.out.println(pm.getObjectById(Greeting.class, g.getId()));
	}

	@After
	public void tearDown() throws Exception {
		if(pm != null)
			pm.close();
		ApiProxy.setEnvironmentForCurrentThread(null);
		ApiProxy.setDelegate(null);
	}
}

ぬるぽ。orz

java.lang.NullPointerException
	at com.google.appengine.api.NamespaceManager.get(NamespaceManager.java:71)
	at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppIdNamespace(DatastoreApiHelper.java:81)
	at com.google.appengine.api.datastore.DatastoreApiHelper.getCurrentAppIdNamespace(DatastoreApiHelper.java:73)
	at com.google.appengine.api.datastore.Key.<init>(Key.java:100)
	at com.google.appengine.api.datastore.Key.<init>(Key.java:85)
	at com.google.appengine.api.datastore.Key.<init>(Key.java:81)
	at com.google.appengine.api.datastore.Entity.<init>(Entity.java:103)
	at com.google.appengine.api.datastore.Entity.<init>(Entity.java:84)
	at org.datanucleus.store.appengine.DatastoreFieldManager.<init>

とりあえずの回避方法

NamespaceManagerのとこでエラーになってたので、TestEnvironmentを以下のようにすることで回避。

public class TestEnvironment implements ApiProxy.Environment {
    public String getAppId() {
        return "Unit Tests";
    }

    public String getVersionId() {
        return "1.0";
    }
    
    public Map<String, Object> getAttributes() {
        Map<String, Object> ret = new HashMap<String, Object>();
        ret.put(NamespaceManager.class.getName() + ".default_api_namespace_key", "test");
        return ret;
    }
    ...
}

グリーンきた!!