11

我正在尝试为我的 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 正在查看的静态不同。这使得跳过对当前测试不重要的功能(例如,需要登录)、注入失败、注入模拟等变得具有挑战性。这确实限制了我测试代码的完整和有效程度。

我发现网络上真正缺乏与 App Engine 进行集成测试的文档。我敢肯定有人以前做过这个……有什么技巧或资源可以分享吗?

4

2 回答 2

2

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

  1. 添加两个 servlet(或其他),它们必须仅在 testing 期间启用,它允许您远程调用帮助程序的 setup 和 teardown。
  2. 让您的 servlet 引擎以完全单线程的方式处理请求。这是必需的,因为出于某种原因,Google 提供的 Helper 类仅在当前线程中生效。
于 2012-09-06T09:59:25.660 回答
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"));
  }
}

现在我遇到的问题是,如果您有两个这样的测试,每个测试都单独通过,您就不能在同一个二进制文件中运行它们。该文件第 37 行的异常被抛出:

IllegalStateException("Dev Appserver 已经在运行。")

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

于 2015-04-12T12:21:41.533 回答