2012-07-31 157 views
10

我正在嘗試爲我的GAE/j應用程序開發一些有效的集成測試。我熟悉https://developers.google.com/appengine/docs/java/tools/localunittesting - 這些工具非常適合小型單元測試。我現在對開發測試實際Web請求的集成測試感興趣。例如,我想測試web.xml是否將servlet和過濾器映射到期望的URL,並測試我的JSP生成我所期望的。Google App Engine的集成測試(java)

我的目標是在JVM內創建一個本地開發服務器,我可以發起請求。不過,我願意接受其他整合策略。正如我上面所說的,我只是想有效地測試JSP生成和其他請求級別的功能。

我已經設法使用DevAppServerFactory在同一個JVM中啓動一個開發服務器。但是,它生成的DevAppServer似乎使用主JVM中的單獨類加載器。這使得測試更具挑戰性 - 我不能使用任何本地單元測試Local * TestConfig類來控制此服務器的行爲。同樣,我不能通過例如「滾動自己的」鉤子來修改行爲。靜態,因爲我可以在測試工具中修改的靜態數據與DevAppServer正在查看的靜態數據不同。這使得跳過當前測試不重要的功能(例如需要登錄),注入失敗,注入模擬等等,這是非常具有挑戰性的。這確實限制了我可以完全有效地測試我的代碼的方式。

我發現網上的文檔真的很缺乏與App Engine進行集成測試。我確信有人已經這樣做過...有沒有可以分享的任何提示或資源?

回答

2

基本上,你需要做兩件事情:

  1. 添加兩個servlet(或其他),必須測試,它允許您可以遠程調用的建立和拆除的助手期間纔會啓用。
  2. 使您的servlet引擎服務請求以完全單線程的方式。這是必要的,因爲由於某種原因,Helper類Google只在當前線程中生效。
0

我同意這個問題記錄不完整。
我設法編寫了一個端到端的測試,將服務器啓動爲一個黑盒子並向它發送HTTP請求。

它的工作原理是這樣的:

package com.project.org; 

import static org.junit.Assert.assertEquals; 
import java.io.File; 
import java.net.MalformedURLException; 
import java.net.URL; 
import java.util.ArrayList; 
import java.util.List; 
import org.junit.After; 
import org.junit.Before; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import com.google.appengine.api.urlfetch.HTTPResponse; 
import com.google.appengine.api.urlfetch.URLFetchServiceFactory; 
import com.google.appengine.tools.development.testing.BaseDevAppServerTestConfig; 
import com.google.appengine.tools.development.testing.DevAppServerTest; 
import com.google.appengine.tools.development.testing.DevAppServerTestRunner; 
import com.google.appengine.tools.development.testing.LocalServiceTestHelper; 

@RunWith(DevAppServerTestRunner.class) 
@DevAppServerTest(HelloWorldTest.TestConfig.class) 
public class HelloWorldTest { 

    public class TestConfig extends BaseDevAppServerTestConfig { 

    @Override public File getSdkRoot() { 
     // You may need to tweak this. 
     return new File("../../appengine-java-sdk-1.9.15"); 
    } 

    @Override public File getAppDir() { 
     return new File("war"); 
    } 

    @Override 
    public List<URL> getClasspath() { 
     // There may be an easier way to do this. 
     List<URL> classPath = new ArrayList<>(); 
     try { 
     String separator = System.getProperty("path.separator"); 
     String[] pathElements = System.getProperty("java.class.path").split(separator); 
     for (String pathElement : pathElements) { 
      classPath.add(new File(pathElement).toURI().toURL()); 
     } 
     } 
     catch (MalformedURLException e) { 
     throw new RuntimeException(e); 
     } 
     return classPath; 
    } 
    } 

    private final LocalServiceTestHelper testHelper; 
    private final String port; 

    public HelloWorldTest() { 
    testHelper = new LocalServiceTestHelper(); 
    port = System.getProperty("appengine.devappserver.test.port"); 
    } 

    @Before public void setUpServer() { 
    testHelper.setUp(); 
    } 

    @After public void tearDown() { 
    testHelper.tearDown(); 
    } 

    @Test public void testHelloWorld() throws Exception { 
    URL url = new URL("http://localhost:" + port + "/hello"); 
    HTTPResponse response = URLFetchServiceFactory.getURLFetchService().fetch(url); 
    assertEquals(200, response.getResponseCode()); 
    assertEquals("Hello world!", new String(response.getContent(), "UTF-8")); 
    } 
} 

現在我的問題是,如果你有兩個那些測試,每個單獨路過,你不能在相同的二進制運行它們。 上線異常的this file 37拋出:

IllegalStateException異常( 「開發應用程序服務器已經運行。」)

不知道如何解決這個問題。