For example, I have a class, working with HttpClient
public class DomainActions : IDomainActions
{
private readonly HttpClient _client;
private readonly IConfiguration _configuration;
public DomainActions(IConfiguration configuration)
{
_configuration = configuration;
_client = new HttpClient()
{
BaseAddress = new Uri(_configuration.GetSection("DomainRegistration:BaseAddress").Value)
};
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _configuration.GetSection("DomainRegistration:Token").Value);
}
public async Task<List<DomainDto>> GetDomainListAsync()
{
var responseMessage = await _client.GetAsync("domains");
return await ProcessingDomainListResponseAsync(responseMessage);
}
then we resolve it by the following way:
services.AddTransient<IConfiguration>(....);
services.AddTransient<IDomainActions, DomainActions>();
and client class:
public class AddMxRecordToRegistrator
{
protected readonly IDomainActions domainActions;
public AddMxRecordToRegistrator(IDomainActions domainActions )
{
this.domainActions = domainActions ;
}
public async Task CreateDomainRecordAsync()
{
await domainActions.CreateDomainRecordAsync(queueItem.DomainForRegistration.DomainName, new DomainRegistrationCore.Models.DomainRecordDto
{
Content = queueItem.MxRecord,
Name = String.Empty,
Priority = 0,
Ttl = 3600,
Type = DomainRecordType.MX.ToString(),
Regions = null
});
ok, it works fine.
Right now, I want to create unit test for AddMxRecordToRegistrator class , but I don't want to use real httpClient. How to do it? Of course, I can add one more dependency:
public class DomainActions : IDomainActions
{
private readonly HttpClient _client;
private readonly IConfiguration _configuration;
public DomainActions(IConfiguration configuration, HttpMessageHandler httpMessageHandler)
{
_configuration = configuration;
_client = new HttpClient(httpMessageHandler)
{
BaseAddress = new Uri(_configuration.GetSection("DomainRegistration:BaseAddress").Value)
};
_client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", _configuration.GetSection("DomainRegistration:Token").Value);
}
public DomainActions(IConfiguration configuration) : this(configuration, new HttpClientHandler())
{
}
public async Task<List<DomainDto>> GetDomainListAsync()
{
var responseMessage = await _client.GetAsync("domains");
return await ProcessingDomainListResponseAsync(responseMessage);
}
then modify DI composition root:
services.AddTransient<IConfiguration>(....);
services.AddTransient<HttpMessageHandler>(....);
services.AddTransient<IDomainActions, DomainActions>();
but then why client part (in our case composition root) should know anything about internal detail of DomainActions
only because we need to create unit test? It like we violate incapsulation for unit tests. How to implement it correctly?