2012-07-31 174 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异常( “开发应用程序服务器已经运行。”)

不知道如何解决这个问题。