2013-06-11 2 views
1

Я использую библиотеку Twilio, и в частности, я пытаюсь ввести макет TwilioRestClient при тестировании.Java: создание объекта «fit» с типом, в котором базовый класс не реализует интерфейс и не может быть унаследован от

Он не реализует никакого интерфейса. И я не могу добавить его.

Я не могу унаследовать от него, он делает вещи в конструкторе, я не поклонник.

Мне нужно иметь пару методов в макете, которые переопределяют или заменяют определенное поведение 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); 

} 
+0

По определению вы не сможете _override_ любых методов без наследования. – DannyMo

+0

Вы правы. Я намерен проверить, когда то, что я тестирую, вызывает эти методы, я решаю в тесте, что методы вернут. В принципе, просто инъекционное поведение, как-то. – Phil

+0

Попробуйте jmockit для переопределения методов. – Jayan

ответ

0

Я закончил тем, что написал слой абстракции, чтобы скрыть всю специфическую логику twilio и сделать код более пригодным для тестирования. Другого способа добиться того, чего я хотел, не было.

0

Насколько я могу видеть TwilioRestClient не конечный класс, так что у вас нет никаких проблем, чтобы расширить его и переопределить все не privete метод.

Во-вторых, здесь есть исходный код TwilioRestClient я нашел here:

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 пустым строком, который звучит хорошо. Но если вы хотите сделать что-то подобное, вы можете сделать это, используя отражение, как только создается экземпляр.

+0

Спасибо, я уточню свой вопрос с версией. Это не выглядит одинаково. – Phil

+0

Обновлен мой вопрос, чтобы показать версию и конструкторы. – Phil

+0

Ну, а какие изменения поведения конструктора вам нужны? – AlexR

2

Вы хотели бы избежать использования фреймворка, и вы не хотите расширять/переопределять TwilioRestClient.

Таким образом, для этого можно использовать свой класс, который использует 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(); 
    } 
}); 

Это будет громоздким, если вы используете много интерфейса; в этом случае, макетные библиотеки действительно лучший выбор, для чего они нужны.

+0

интересный подход, я исследую этот вариант. Благодаря! – Phil

Смежные вопросы