我正在为严重依赖 Google App Engine 服务(如 Memcache 和 Datastore)的 Google App Engine Java 应用程序编写测试(集成和单元)。为了使用这些服务在本地测试我的应用程序,我在所有测试用例的父类中都有这一行:
private final LocalServiceTestHelper helper = new LocalServiceTestHelper(new LocalDatastoreServiceTestConfig(), new LocalMemcacheServiceTestConfig());
我用这个函数调用开始每个测试(通过TestNG的@BeforeMethod
注释):
helper.setUp();
我用这个函数调用结束每个测试(通过TestNG的@AfterMethod
注释):
helper.tearDown();
(这里参考了TestNG annotations and local unit testing for Google App Engine's Java Runtime,以备不时之需。尤其是后面的链接,请注意我的代码严格遵循Google给出的示例)
需要注意的一点是,我在 Java 应用程序中的一个 servlet 使用了 MemcacheService 实例。它被 Guice 注入到 servlet 的构造函数中。
现在,我构建我的代码并通过调用来运行它mvn clean install
,这将启动一个Jetty实例并在代码编译后运行我的测试。令我懊恼的是,我在 TestNG 报告大规模测试失败之前打印了这个堆栈跟踪:
SEVERE: Received exception tearing down config of type com.google.appengine.tools.development.testing.LocalMemcacheServiceTestConfig
java.lang.NullPointerException
at com.google.appengine.tools.development.testing.LocalServiceTestHelper.getLocalService(LocalServiceTestHelper.java:495)
at com.google.appengine.tools.development.testing.LocalMemcacheServiceTestConfig.getLocalMemcacheService(LocalMemcacheServiceTestConfig.java:71)
at com.google.appengine.tools.development.testing.LocalMemcacheServiceTestConfig.tearDown(LocalMemcacheServiceTestConfig.java:47)
at com.google.appengine.tools.development.testing.LocalServiceTestHelper.tearDown(LocalServiceTestHelper.java:438)
at com.ea.pogosocial.AbstractTest.tearDown(AbstractTest.java:65)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:616)
at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:80)
at org.testng.internal.Invoker.invokeConfigurationMethod(Invoker.java:564)
at org.testng.internal.Invoker.invokeConfigurations(Invoker.java:213)
at org.testng.internal.Invoker.invokeMethod(Invoker.java:796)
at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:907)
at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:1237)
at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:127)
at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:111)
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
at java.lang.Thread.run(Thread.java:679)
我已经尝试了几乎所有我能想到的来解决这个问题,但我仍然遇到了这个 tearDown() 问题,这真的让我很困惑。除了 put() 和 get(),我没有对 servlet 中的 memcache 实例做任何花哨的事情。有人对我应该做什么有任何想法吗?
如果需要更多信息或代码,我很乐意提供。需要注意的一件事:当我启动我的 Jetty 服务器mvn gae:run
并通过 Eclipse 执行 TestNG 测试时,我没有遇到这个问题。也许这是因为我的 servlet 被注入了一个非本地的 memcache 单元测试助手实例,而是一个实际版本的 memcache 服务。