4

在我的應用程序中,我有一組DAO,我將其注入應用程序層。對於我正在編寫的驗收測試,我想用數據預加載dev_server數據存儲,所以我在我的JUnit測試中使用相同的Spring配置(使用@ContextConfiguration註釋)將相關DAO的實例注入到我的測試中。當我真的去存儲一些數據,例如:驗收測試將數據預加載到GAE開發服務器數據存儲區

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

我找到了解決方案!

由於某些原因,測試數據存儲的Namespace,AppID和AuthDomain字段必須與dev_server的字段匹配,那麼dev_server可以看到測試插入的實體。 (:gaeHelper EG),可以爲測試環境

設置的值

你可以用下面的語句

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

在你LocalServiceTestHelper的實例請參閱環境(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將不會看到它,除非它可能被強制重新讀取該文件(我還沒有弄清楚)。否則,服務器必須重新啓動。

3

Here是一個頁面,介紹如何執行連接到開發數據存儲的單元測試。這是你尋找的東西嗎?基本上它講述了兩個類,LocalServiceTestHelper和LocalDatastoreServiceTestConfig,您可以使用它們來設置測試環境。雖然給出的例子是單元測試,但我相信它也適用於您的情況。

然後,您可以配置開發數據存儲區是寫入磁盤還是保存在內存中(以便更快地進行測試)。如果你想讓這些數據到你的開發服務器的相同位置,你可能會想調整它,因爲我認爲默認值是「內存」選項。如果你看javadoc,有一個「setBackingStoreLocation」方法,你可以指向你想要的任何文件。

+0

我嘗試在測試中設置數據存儲後備存儲(使用LocalDatastoreServiceTestConfig)與dev_server寫入的文件相同(例如:WEB-INF/appengine-generated/local_db.bin)並且測試會成功寫入實體到文件。但是,當我啓動dev_server並查看管理控制檯時,不會顯示寫在測試中的實體。 如果我運行另一個查詢數據存儲的測試(使用LocalDatastoreServiceTestConfig),則找到該實體。 該實體正在數據存儲中結束,但運行在dev_server上的應用程序無法看到它。 – kierans 2011-01-24 18:57:57

+0

我認爲它與名稱空間有關,dev_server和LocalServiceTestHelper將實體放入該實體中,導致應用程序不能看到測試實體。閱讀http://code.google.com/appengine/docs/java/multitenancy/multitenancy.html我試着讓測試代碼將這些實體放入應用程序所執行的空('')命名空間中,但應用程序仍然看不到他們。 – kierans 2011-01-29 11:39:35

0

我發現了一種解決方法,雖然它不是很好,因爲每個測試方法都不會清理數據存儲區,正如文章Local Unit Testing for Java中所述,但是,每次運行Test類時,數據存儲區都會開始清理,所以這並不壞,只要你對此謹慎。

的問題是,在使用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(); 
    } 

如果有人有更好的解決方案,我會很高興聽到!

相關問題