加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java – 在GAE之外测试Google App Engine ThreadManager

发布时间:2020-12-14 06:08:08 所属栏目:Java 来源:网络整理
导读:我编写了一个JUnit(4.10)单元测试,它对com.google.appengine.api.ThreadManager进行了以下调用: ThreadManager.currentRequestThreadFactory(); 当这个测试运行时,我从这个currentRequestThreadFactory方法中抛出一个NullPointerException: Caused by: jav

我编写了一个JUnit(4.10)单元测试,它对com.google.appengine.api.ThreadManager进行了以下调用:

ThreadManager.currentRequestThreadFactory();

当这个测试运行时,我从这个currentRequestThreadFactory方法中抛出一个NullPointerException:

Caused by: java.lang.NullPointerException
    at com.google.appengine.api.ThreadManager.currentRequestThreadFactory(ThreadManager.java:39)
    at com.myapp.server.plumbing.di.BaseModule.providesThreadFactory(BaseModule.java:50)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)

当我下载ThreadManager的源代码并查看第39行(NPE的源代码)时,我看到:

public static ThreadFactory currentRequestThreadFactory() {
        return (ThreadFactory) ApiProxy.getCurrentEnvironment().getAttributes()
            .get(REQUEST_THREAD_FACTORY_ATTR);
}

因此,似乎ApiProxy.getCurrentEnvironment()为null,并且当调用它的getAttribute()方法时,将抛出NPE.我通过在单元测试代码中添加一些新的打印语句来证实这一点:

if(ApiProxy.getCurrentEnvironment() == null)
    System.out.println("Environment is null.");

我隐约知道GAE为其所有服务提供“测试版本”,但未能(具体地)找到如何使用它们并进行设置.所以我问:GAE是否提供这样的测试版本?如果是这样,我如何在这里添加ApiProxy测试版?如果没有,那么我的选择是什么?我不认为我可以模拟任何一种方法(ThreadManager#currentRequestThreadFactory或ApiProxy#getCurrentEnvironment),因为它们都是静态的.提前致谢.

编辑:我看到SDK附带了一个appengine-testing.jar.在这个JAR里面是一个ApiProxyLocal.class,我相信它是一个可以在JUnit测试期间使用的ApiProxy版本,它可以在不抛弃NPE的情况下工作.如果是这种情况(我甚至不确定),那么问题是:如何将它注入我的ThreadManager进行此测试?

最佳答案
我建议不要直接从你的代码调用ThreadManager.currentRequestThreadFactory().相反,将ThreadFactory注入需要创建线程的类中.

一个简单的方法是使用Guice:

public static class MyService {
  private final ThreadFactory threadFactory;

  @Inject
  MyService(ThreadFactory threadFactory) {
    this.threadFactory = threadFactory;
  }

  ...
}

在MyService的测试中,您可以将假的ThreadFactory传递给MyService构造函数,也可以注入Executors.defaultThreadFactory().

在您的生产代码中,您将创建一个绑定:

bind(ThreadFactory.class)
    .toInstance(ThreadManager.currentRequestThreadFactory());

当然,如果你还没准备好进入依赖注入,你可以创建自己的访问器来获取和设置ThreadFactory

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读