2013-02-04 19 views
5

の外で私はcom.google.appengine.api.ThreadManagerに、次の呼び出しを行うJUnitの(4.10)ユニットテスト書いている:このテストを実行すると、私はNullPointerExceptionが内からスローされますテストGoogle App EngineのThreadManager GAE

ThreadManager.currentRequestThreadFactory(); 

をこのcurrentRequestThreadFactory方法:

Caused by: java.lang.NullPointerException 
    at com.google.appengine.api.ThreadManager.currentRequestThreadFactory(ThreadManager.java:39) 
    at com.myapp.server.plumbing.di.BaseModule.providesThreadFactory(BaseModule.java:50) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) 

私はThreadManagerのソースをプルダウン、及び(NPEの源である)ライン39を見ると、私は次を参照してください。

public static ThreadFactory currentRequestThreadFactory() { 
     return (ThreadFactory) ApiProxy.getCurrentEnvironment().getAttributes() 
      .get(REQUEST_THREAD_FACTORY_ATTR); 
} 

したがって、ApiProxy.getCurrentEnvironment()がnullであると思われ、getAttribute()メソッドが呼び出されると、NPEがスローされます。私はGAEは、すべてのサービスのために、「テスト版」を提供することを漠然と意識してる

if(ApiProxy.getCurrentEnvironment() == null) 
    System.out.println("Environment is null."); 

が、することができていない:私は私のユニットテストコードに高いいくつかの新しいprint文を追加することで、これを確認しましたどのようにそれらを使用し、それらを設定するか(特に)を見つける。だから私は尋ねる:GAEはそのようなテストバージョンを提供していますか?その場合は、ここにApiProxyテストバージョンを追加するにはどうすればよいですか?そうでなければ、私の選択肢は何ですか?どちらの方法も模倣できるとは思わない(ThreadManager#currentRequestThreadFactoryまたはApiProxy#getCurrentEnvironment)。前もって感謝します。

を編集します。appengine-testing.jarがSDKに同梱されています。このJARの内部には、がNPEを投げずに動作するJUnitテストで使用できるApiProxyのバージョンであると信じているApiProxyLocal.classがあります。それが事実なら(これは私も確信していません)、問題は次のようなものです。このテストに私のThreadManagerをどうやって注入するのですか?

+0

あなたがhttps://developers.google.com/appengine/docs/java/tools/localunittesting#Introducing_the_Java_Testing_Utilitiesを読みましたか? – NamshubWriter

+0

もう一度ありがとう - これらのテストJAR(その記事で参照されている)は、ローカルの** servce **クラスとメソッドにアクセスできますが、 'ThreadManager'のテストバージョンではありません... – IAmYourFaja

答えて

1

コードから直接ThreadManager.currentRequestThreadFactory()を呼び出すことを避けることをおすすめします。代わりに、スレッドを作成する必要があるクラスにThreadFactoryを挿入します。あなたはMyServiceコンストラクタに偽のThreadFactoryを渡すか、Executors.defaultThreadFactory()を注入可能性のいずれか、MyServiceのためのあなたのテストでは

public static class MyService { 
    private final ThreadFactory threadFactory; 

    @Inject 
    MyService(ThreadFactory threadFactory) { 
    this.threadFactory = threadFactory; 
    } 

    ... 
} 

:これを行うには

簡単な方法としては、Guiceのです。本番コードで

、あなたはバインディング作成します。もちろん

bind(ThreadFactory.class) 
    .toInstance(ThreadManager.currentRequestThreadFactory()); 

を使用すると、依存性の注入にジャンプする準備ができていないのであれば、あなたはThreadFactory

を取得および設定するために、独自のアクセサを作成することができますあなたがを見つけていないところ
+0

ありがとう@NamshubWriter、 * 'ThreadManager'を挿入する方法*。 **私は、JUnitテストの中から 'com.google.appengine.api.ThreadManager.currentRequestThreadFactory'を実行できないと言っています**これは内部的な、静的ではない静的な' ApiProxy.getCurrentEnvironment() 'メソッドがあるためですそれはNPEを投げている。アプリケーションをローカルのGAEアプリケーションサーバーにデプロイしてコードを実行すると、 'ApiProxy.getCurrentEnvironment()'がNPEを投げないため、正常に動作します。だから私はテスト目的のためにGAEの外でこれを実行する方法を理解する必要があります。 – IAmYourFaja

+0

@DirtyMikeAndTheBoys私はあなたがやろうとしていることを知っています。私はちょうどそれについて完全に別の方法を行くことを提案しています。コードは、コントロールとは別の静的なメソッドで、テストではなくプロダクションでは動作が異なります。そのため、コードをテストするのが難しくなります。あなたがコントロールするクラスに応じて問題を解決します。 – NamshubWriter

0

http://code.google.com/appengine/docs/java/howto/unittesting.html

で提案されているように、あなたがApiProxy.Environmentを実装している場合は、getAttributes()方法がありますあなたのマップにのエントリ

あなたはそれを追加することができます。

attributes.put(REQUEST_THREAD_FACTORY_ATTR, new RequestThreadFactory()); 

を他の有用な添加物は、以下を参照してくださいあなたのユニットテストケース内のスレッドを開始している場合 http://googleappengine.googlecode.com/svn-history/trunk/java/src/main/com/google/appengine/tools/development/LocalEnvironment.java

0

は、最後の答えに追加するには、そのJavaのスレッドにはApiProxy環境も必要です。 TEnvironmentは、上記のURLに記載されている

public static void setEnvironment() { 

    if (ApiProxy.getCurrentEnvironment() == null) { 

     ApiProxyLocal apl = LocalServiceTestHelper.getApiProxyLocal(); 

     ApiProxy.setEnvironmentForCurrentThread(new TEnvironment()); 

     ApiProxy.setDelegate(apl); 

    } 
} 

super.setUp(); 

helper1.setUp(); 

setEnvironment(); 

:あなたのクラスLocalServiceTestCaseで

はテストケース、設定方法は、このような になります拡張します。

静的なunsetEnvironment()を作成することもできます。新しいJavaスレッドを開始した場合、あなたのユニットテストケースで

、あなただけ あなたのrunメソッドの開始時に静的メソッドを使用することができます。

public void run() { 

    LocalServiceTestCase.setEnvironment(); 
2

あなたがから正しいスレッドを取得しますLocalServiceTestHelperを設定すると、スタブは次の行に沿って表示されます。

private static final LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig()); 

@BeforeClass 
public static void initialSetup() { 
    helper.setUp(); 
} 

@AfterClass 
public static void finalTearDown() { 
    helper.tearDown(); 
} 
+0

また、helper.setUp()の後にThreadManagerを使用することを忘れないでください。 – ZillGate