Google App Engine的集成测试(java)

时间:2012-07-31 15:41:40

标签: google-app-engine testing integration-testing

我正在尝试为我的GAE / j应用程序开发一些有效的集成测试。我熟悉https://developers.google.com/appengine/docs/java/tools/localunittesting - 这些工具非常适合小型单元测试。我现在对开发测试实际Web请求的集成测试感兴趣。例如,我想测试web.xml是否将servlet和过滤器映射到预期的URL并测试我的JSP生成了我期望的内容。

我的目标是在JVM中调出一个本地开发服务器,我可以发起请求。不过,我对其他整合策略持开放态度;正如我上面所说,我只想有效地测试JSP生成和其他请求级功能。

我设法使用DevAppServerFactory在同一个JVM中启动开发服务器。但是,它生成的DevAppServer似乎使用来自主JVM的单独的类加载器。这使得测试更具挑战性 - 我不能使用任何本地单元测试Local * TestConfig类来控制此服务器的行为。类似地,我不能通过例如“滚动我自己的”钩子来修改行为。静态,因为我可以在测试工具中变异的静态与DevAppServer所关注的静态不同。这使得跳过不是当前测试中心的功能(例如需要登录),注入失败,注入模拟等等具有挑战性。这实际上限制了我可以完全有效地测试代码的方式。

我发现Web上的文档很少用于与App Engine进行集成测试。我确定之前有人已经这样做了......你们可以分享哪些提示或资源?

2 个答案:

答案 0 :(得分:2)

基本上,你需要做两件事:

  1. 添加两个servlet(或其他),必须仅在测试期间启用,这允许您远程调用帮助程序的设置和拆卸。
  2. 使您的servlet引擎以完全单线程方式提供请求。这是必需的,因为出于某种原因,Google提供的Helper类仅在当前线程中生效。

答案 1 :(得分: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(&#34; Dev Appserver已在运行。&#34;)

不确定如何解决此问题。