I am trying to write my first real library.In my case it will provide a java/kotlin API for sending network calls to a server.I am a big fan of TDD and would like to code the library in the same way.Normally I would now separate the networking code from the other code to test if the networking class gets called correctlypublic 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    }}and the testpublic 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()    }}But in the case of a library I cannot quite do that.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.Of course I could create an overloaded constructor just for testing:public class SpecialServerClient {    private final HttpClient httpClient;    public SpecialServerClient(){        this.httpClient = RealHttpClient();    }    public SpecialServerClient(HttpClient httpClient){        this.httpClient = httpClient;    }}but now I am adding production code for the sake of testing,which is not that great either. Is there a better way to solve this?
Is it possible to inject dependencies when writing a library?
design;testing;tdd;dependency injection
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.How is it a burden on the user if you're providing a default dependency (as you do with the zero-arg constructor)?but now I am adding production code for the sake of testing,It's not only for the sake of testing. By exposing the DI method, you're making your library more flexible. It's highly likely that some clients will want to configure their http client themselves. For example it's a very common requirement to configure things like SSL and timeouts on the client. They may not want to use RealHttpClient, and the user may want to mock this in their own integration tests.What are the downsides to having the DI constructor?