E 'possibile iniettare dipendenze quando si scrive una libreria?

4

Sto cercando di scrivere la mia prima libreria "reale".
Nel mio caso fornirà un'API java / kotlin per l'invio di chiamate di rete a un server.

Sono un grande fan di TDD e vorrei codificare la libreria allo stesso modo.
Normalmente ora separerei il codice di rete dall'altro codice per verificare se la classe di rete viene chiamata correttamente

public class SpecialServerClient {

    private final HttpClient httpClient;

    public SpecialServerClient(HttpClient httpClient){
        this.httpClient = httpClient;
    }

    public void sendData(Data data){
        //Do things with data
        //Create request for data
        //Pass request to httpClient
    }
}

e il test

public class SpecialServerClientTest {

    @Mock HttpClient httpClient;

    private SpecialServerClient specialServerClient;

    @Before
    public void setUp(){
        specialServerClient = new SpecialServerClient(httpClient)
    }

    @Test
    public void testSendData(){
        Data data = //Create fake data

        specialServerClient.sendData(data);

        verify(httpClient).calledWithRequestWithTransformedData()
    }
}

Ma nel caso di una biblioteca non posso proprio farlo.
Non voglio sovraccaricare gli utenti dell'API per fornire un HttpClient anche se la libreria fornisce un'implementazione predefinita / reale per loro.

Ovviamente potrei creare un costruttore sovraccarico solo per il test:

public class SpecialServerClient {

    private final HttpClient httpClient;

    public SpecialServerClient(){
        this.httpClient = RealHttpClient();
    }

    public SpecialServerClient(HttpClient httpClient){
        this.httpClient = httpClient;
    }
}

ma ora aggiungo il codice di produzione per motivi di testing,
che non è poi così grandioso.

C'è un modo migliore per risolvere questo?

    
posta Altoyr 31.07.2017 - 23:29
fonte

2 risposte

8

I do not want to burden the users of the API to provide a HttpClient even if the library provides a default/real implementation for them.

Come è un peso per l'utente se stai fornendo una dipendenza predefinita (come fai con il costruttore di zero-arg)?

but now I am adding production code for the sake of testing,

Non è solo per il gusto di testare. Esponendo il metodo DI, rendi la tua libreria più flessibile. È molto probabile che alcuni client vogliano configurare da soli il proprio client http. Ad esempio è un requisito molto comune configurare cose come SSL e timeout sul client. Potrebbero non voler utilizzare RealHttpClient e l'utente potrebbe voler prendere in giro questo nei propri test di integrazione.

Quali sono gli svantaggi di avere il costruttore DI?

    
risposta data 31.07.2017 - 23:40
fonte
1

Esaminando solo SpecialServerClient , è corretto dipendere da HttpClient . Non dovrebbe preoccuparsi di come viene creata una HttpClient . Se non vuoi "appesantire" gli utenti della biblioteca di scegliere / creare un HttpClient , puoi fornire un factory di convenienza che crea SpecialServerClient con un HttpClient predefinito. In pratica muovi la creazione dell'oggetto in un posto diverso (se stai bene non testando la fabbrica stessa).

    
risposta data 01.08.2017 - 00:01
fonte

Leggi altre domande sui tag