1

我正在使用 Twilio 库,特别是我试图在测试时注入 TwilioRestClient 的模拟。

它没有实现任何接口。我不能添加一个。

我不能从它继承,它在我不喜欢的构造函数中做了一些事情。

我需要在模拟中有几个方法来覆盖或替换 TwilioRestClient 的某些行为。

我该怎么做呢?

我试过内部匿名类无济于事。我已经尝试过子类化,但显然不起作用。那里有 Java 大师吗?

编辑,twilio sdk 版本;

public class TwilioRestClient {
    /** The Constant VERSION. */
    private static final String VERSION = "3.3.15";

构造函数:

    /**
 * Explcitly construct a TwilioRestClient with the given API credentials.
 *
 * @param accountSid
 *            the 34 character Account identifier (starting with 'AC'). This
 *            can be found on your Twilio dashboard page.
 * @param authToken
 *            the 32 character AuthToken. This can be found on your Twilio
 *            dashboard page.
 *
 */
public TwilioRestClient(String accountSid, String authToken) {
    this(accountSid, authToken, null);
}

/**
 * Explcitly construct a TwilioRestClient with the given API credentials and
 * endpoint.
 *
 * @param accountSid
 *            the 34 character Account identifier (starting with 'AC'). This
 *            can be found on your Twilio dashboard page.
 * @param authToken
 *            the 32 character AuthToken. This can be found on your Twilio
 *            dashboard page.
 * @param endpoint
 *            the url of API endpoint you wish to use. (e.g. -
 *            'https://api.twilio.com')
 */
public TwilioRestClient(String accountSid, String authToken, String endpoint) {

    validateAccountSid(accountSid);
    validateAuthToken(authToken);

    this.accountSid = accountSid;
    this.authToken = authToken;

    if ((endpoint != null) && (!endpoint.equals(""))) {
        this.endpoint = endpoint;
    }

    //Grab the proper connection manager, based on runtime environment
    ClientConnectionManager mgr = null;
    try {
        Class.forName("com.google.appengine.api.urlfetch.HTTPRequest");
        mgr = new AppEngineClientConnectionManager();
    } catch (ClassNotFoundException e) {
        //Not GAE
        mgr = new ThreadSafeClientConnManager();
        ((ThreadSafeClientConnManager) mgr).setDefaultMaxPerRoute(10);
    }

    setHttpclient(new DefaultHttpClient(mgr));
    httpclient.getParams().setParameter("http.protocol.version",
            HttpVersion.HTTP_1_1);
    httpclient.getParams().setParameter("http.socket.timeout",
            new Integer(CONNECTION_TIMEOUT));
    httpclient.getParams().setParameter("http.connection.timeout",
            new Integer(CONNECTION_TIMEOUT));
    httpclient.getParams().setParameter("http.protocol.content-charset",
            "UTF-8");

    this.authAccount = new Account(this);
    this.authAccount.setSid(this.accountSid);
    this.authAccount.setAuthToken(this.authToken);

}
4

3 回答 3

2

您想避免使用模拟框架,并且不想扩展/覆盖 TwilioRestClient。

那么,执行此操作的“纯 Java”方法可能是让使用 TwilioRestClient 的类使用您定义的接口。这样做的难度取决于您实际使用了多少 TwilioRestClient 接口。

如果您只使用几种方法,请定义自己的接口,例如:

public interface RestClient {
    String get(String uri);
}

当您想使用 TwilioRestClient 时,您可以:

final TwilioRestClient trc = createTwilioRestClient();
myService.setRestClient(new RestClient() {
    public String get(String uri) {
        return trc.get(uri);
    }
});

当您想进行单元测试时,请使用:

myService.setRestClient(new RestClient() {
    public String get(String uri) {
        return someMockData();
    }
});

但是,如果您使用大量界面,这将变得笨拙;在这种情况下,模拟库确实是您最好的选择,这就是它们的用途。

于 2013-06-11T16:39:51.363 回答
0

据我所知,TwilioRestClient它不是最终类,因此您可以毫无问题地扩展它并覆盖每个非私有方法。

TwilioRestClient其次,这是我在这里找到的源代码:

private String endpoint = "https://api.twilio.com";
private String accountSid;
private String authToken;


public TwilioRestClient(String accountSid, String authToken, String endpoint) {

    this.accountSid = accountSid;
    this.authToken = authToken;
    if((endpoint!=null)&&(!endpoint.equals(""))){
        this.endpoint = endpoint;
    }
}

正如我们所见,它只是将三个字符串字段初始化到构造函数中。所以,我认为你可以发送任何你想要的参数,甚至不必扩展类。但是,我不确定我找到的源代码是否属于您正在使用的同一版本。您没有指定版本。

您在这里的唯一限制是您无法初始化endopoint为听起来不错的空字符串。但是如果你想做类似的事情,你可以在创建实例后使用反射来做到这一点。

于 2013-06-11T16:17:48.287 回答
0

我最终编写了一个抽象层来隐藏所有 twilio 特定逻辑并使代码更易于测试。没有其他方法可以实现我想要的。

于 2013-06-16T12:40:38.843 回答