0

I have the following code and I want to unit test it, as below

  public class MarketLiability : IMarketLiability
    {
        private readonly string serviceAddress;

        private readonly ILogger<MarketLiability> logger;

        private readonly string marketLiabilityAddress

        private readonly string clientId;

        private readonly string secret;

        public MarketLiability(ILogger<MarketLiability> logger, IEnvironmentVariableRetriever varRetriever) 
        {
            this.logger = logger;
            this.marketLiabilityAddress = varRetriever.GetEnvironmentVariable("baseUrl");
            this.serviceAddress = varRetriever.GetEnvironmentVariable("ServiceAddress");
            this.clientId = varRetriever.GetEnvironmentVariable("ClientId");
            this.secret = varRetriever.GetEnvironmentVariable("Secret");
        }
        public async Task<Quotes> GetMarketQuotes()
        {
            this.logger.LogInformation("Fetching all market quotes");

            var uri = "quotes";

        var token = GetAccessToken();

            var client = new HttpClient();

            var request = new HttpRequestMessage(HttpMethod.Get, $"{this.marketLiabilityAddress}/{uri}");

            request.Headers.Add("Authorization", $"Bearer {token}");

            var response = await client.SendAsync(request);

            var content = await response.Content.ReadAsStringAsync();

            var result = JsonConvert.DeserializeObject<Quotes>(content);

            return result;
        }
}
    public interface IMarketLiability
    {
        Task<Quotes> GetMarketQuotes();
    }

I have an integration test that works, but I need to unit test it with fake Urls, clientid, secret

[Fact]
public void TestMockConnection()
{
// Arrange
    environmentVariableRetrieverMock = new Mock<IEnvironmentVariableRetriever>();
    this.environmentVariableRetrieverMock
        .Setup(x => x.GetEnvironmentVariable("baseUrl"))
        .Returns("some actual url");

    this.environmentVariableRetrieverMock
        .Setup(x => x.GetEnvironmentVariable("ServiceAddress"))
        .Returns("some actual url");

    this.environmentVariableRetrieverMock
        .Setup(x => x.GetEnvironmentVariable("ClientId"))
        .Returns("ClientId"); 

    this.environmentVariableRetrieverMock
        .Setup(x => x.GetEnvironmentVariable("Secret"))
        .Returns("Secret"); 

    var marketLiability = new MarketLiability(this.loggerMock.Object, this.environmentVariableRetrieverMock.Object);

    // Act
    var response = await marketLiability.GetMarketQuotes();

    // Assert
    response.Should().NotBeNull();
    response.Should().BeOfType<Quotes>();
}  

How can I unit test this without having to put the actual Url. I tried a fake Url and when it come to the line var response = await marketLiability.GetMarketQuotes();it fails with an invalid Url error.

Any ideas?

Thanks

Garry A
  • 383
  • 5
  • 19
  • Not every method is **unit** testable. It will only be, if **any** dependency is mockable. Your method uses HttpClient as a dependency in a way you cannot mock that. Well you can do **integration** tests on that, but that is a different thing. – Sir Rufo Nov 03 '20 at 10:29
  • Is there a way of rewriting this, in order to unit test it? – Garry A Nov 03 '20 at 10:40
  • Yes, of course. Replace the HttpClient with a mockable thing (f.i. a [RequestProvider](https://github.com/microsoft/BikeSharing360_MobileApps/blob/58dec47baea08cd05170a3a06025b62a493c0296/src/BikeSharing.Clients.Core/DataServices/Base/RequestProvider.cs)) – Sir Rufo Nov 03 '20 at 10:47
  • 1
    You should NOT create a new HttpClient for every request. This is a well known problem, which has been solved with HttpClientFactory. See here on how to unit test HttpClientFactory https://stackoverflow.com/questions/54227487/how-to-mock-the-new-httpclientfactory-in-net-core-2-1-using-moq – Neil Nov 03 '20 at 11:04
  • Thanks for that, but I can't see how this is going to work with my unit tests in my code. Still is asking for a valid Uri. Could you provide a sample test? – Garry A Nov 03 '20 at 11:04
  • Does this answer your question? [How to mock the new HttpClientFactory in .NET Core 2.1 using Moq](https://stackoverflow.com/questions/54227487/how-to-mock-the-new-httpclientfactory-in-net-core-2-1-using-moq) – Neil Nov 03 '20 at 11:04
  • Partly yes, however I have the IEnvironmentVariableRetriever in the constructor that contains all the urls and clientIds and secret. How can I make that with fake Urls? – Garry A Nov 03 '20 at 11:16

0 Answers0