4

私のアプリケーションでは、アプリケーションレイヤーに注入する一連のDAOがあります。私が書いている受け入れテストでは、dev_serverデータストアにデータをプリロードしたいので、JUnitテスト(@ContextConfigurationアノテーションを使用)で同じSpring設定を使用して、関連するDAOのインスタンスをテストに挿入します。実際にデータを保存するときなど:GAE devサーバーデータストアへのデータの受け入れテストの事前テスト

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アプリケーション-web.xmlに読まれていないためと考えられます。そのため、dev_server上で実行されているアプリケーションが読み取り/書き込みを行っているのと同じデータストアに書き込むことは知られていません。

私のテストをアプリと同じデータストアに "ポイント"させるにはどうすればよいですか?私はアプリとテストの両方に注入できるいくつかの "データソース"メカニズムがありますか?私のテストでデータストアのAPIに必要な設定を読み込ませる方法がありますか?

答えて

0

解決策を見つけました。

何らかの理由で、テストデータストアのネームスペース、AppID、AuthDomainフィールドがdev_serverのフィールドと一致する必要がある場合、dev_serverはテストによって挿入されたエンティティを認識できます。あなたは次の文LocalServiceTestHelper(例:gaeHelper)のインスタンスで

System.out.println(NamespaceManager.get()); 
System.out.println(ApiProxy.getCurrentEnvironment().getAppId()); 
System.out.println(ApiProxy.getCurrentEnvironment().getAuthDomain()); 

と環境(dev_serverまたはテストコード)の値を見ることができます

、あなたはテスト環境に値を設定することができます

// 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はファイルを読み直さなければdev_serverはそれを見ません(私はまだ分かりません)。それ以外の場合は、サーバーを再起動する必要があります。

+0

残念ながら、このアプローチはGAE <1.4.2(1.4.0を使用していました)でのみ動作します。このソリューションを無効にしたバージョン間で、API内の何かが変更されている必要があります。 – kierans

3

Hereは、devデータストアに接続する単体テストを行う方法について説明しているページです。これはあなたが探しているものですか?基本的には、テスト用の環境を設定するために使用できるLocalServiceTestHelperとLocalDatastoreServiceTestConfigの2つのクラスについて説明します。与えられた例は単体テストのためのものですが、あなたの状況にも当てはまると思います。

これで、devデータストアがディスクに書き込まれているのか、メモリに保存されているのか(速いテストのため)のような設定ができます。このデータをあなたのdevサーバと同じ場所に移動したい場合は、デフォルトで「メモリ内」オプションと思うので、おそらくこれを調整したいでしょう。 javadocを見ると、 "setBackingStoreLocation"メソッドがあり、そこから任意のファイルを指すことができます。

+0

dev_serverが書き込むのと同じファイル(例:WEB-INF/appengine-generated/local_db.bin)になるようにテストでのデータストアバッキングストア(LocalDatastoreServiceTestConfigを使用)を設定しようとしましたが、ファイルに追加します。しかし、私がdev_serverを起動して管理コンソールを見ると、テストで書かれたエンティティは表示されません。 (LocalDatastoreServiceTestConfigを使用して)データストアを照会する別のテストを実行すると、そのエンティティが検出されます。 エンティティはデータストアで終了していますが、dev_server上で実行されているアプリケーションはそれを見ることができません。 – kierans

+0

dev_serverとLocalServiceTestHelperがエンティティを配置している名前空間と何か関係があると思うので、テストエンティティが表示されないようにしています。 http://code.google.com/appengine/docs/java/multitenancy/multitenancy.htmlを読んでいる私は、テストコードで、アプリケーションが行う空の( '))名前空間にエンティティを配置しようとしましたが、アプリケーションまだそれらを見ることはできません。 – kierans

+0

わかりやすくするために、私はNamespaceManager.set()メソッドを使用して、dev_serverコードとテストコードの両方の名前空間を変更していました。私も別の文字列で試してみましたが、それもうまくいきませんでした。 – kierans

0

Local Unit Testing for Javaの記事で説明しているように、各テストメソッドでデータストアがクリーンアップされないため、回避策が見つかりませんでしたが、テストクラスが実行されるたびにデータストアがクリーンアップされますそれはあなたがそれに注意するならば、それほど悪くない。

問題がSpringJUnit4ClassRunnerを使用しているとき@Before注釈が実行される前に、春の環境が作成されていること、である、解決策は@BeforeClassを使用し、春の環境が設定される前に、それらを作成しているために、LocalServiceTestHelperために静的変数を使用しています。

@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(); 
    } 

誰かがより良い解決策を持っていれば、私は聞いてうれしく思います!

関連する問題