3

I have two services that inherit from the same base service. Both make asynchronous API calls that I am writing tests for. I am able to debug through the base service call for one service as expected. For the second service the debugger does not stop at any of the breakpoints after the async call is made, but rather completes execution and exits.

Here is the base service that both services inherit:

namespace MyCoach.Services
{
    public enum Caching { Normal, Forced };
    public abstract class BaseService
    {
        protected readonly INetworkManager _networkManager;
        protected readonly IConfigurationService _configurationService;
        protected readonly ISettingsService _settings;
        protected readonly ICacheService _cache;

        public BaseService(INetworkManager networkManager, IConfigurationService configurationService, ISettingsService settingsService, ICacheService cacheService)
        {
            _networkManager = networkManager;
            _configurationService = configurationService;
            _settings = settingsService;
            _cache = cacheService;
        }

        protected void Execute<T>(RestRequest request, Action<T> onSuccess, Action<HttpStatusCode> onFailure) where T : class, new()
        {
            ExecuteAsync(request, onSuccess, onFailure);
        }

        protected async Task ExecuteAsync<T>(RestRequest request, Action<T> onSuccess, Action<HttpStatusCode> onFailure) where T : class
        {
            if (_networkManager.IsConnectionAvailable())
            {
                var restClient = new RestClient(new Uri(_configurationService.Configuration.MyCoachBaseUrl));
                AddImageSetParameter(request);
                try
                {
                    *IRestResponse<T> response = await restClient.Execute<T>(request);
                    if (IsSuccessfulStatusCode(response.StatusCode))
                    {
                        onSuccess(response.Data);
                    }
                    else
                    {
                        onFailure(response.StatusCode);
                    }
                }
                catch (Exception ex)
                {
                    int statusCode = Int32.Parse(ex.Message.Substring(0, 3));
                    onFailure((HttpStatusCode)Enum.ToObject(typeof(HttpStatusCode), statusCode));
                }
            }
            else
            {
                _networkManager.ShowNetworkUnavailableError();
            }
        }
    }    
}

I can put a breakpoint on the await command in the executeAsync method (marked by an *) that is hit by the debugger when I run either service. Any breakpoint within the if/else or exception handler following that call is not hit as expected when I debug the PingService. Those same breakpoints are hit when I debug the HomeService, so I'm guessing there must be some issue with how I've implemented the PingService.

Here is my service that works as expected:

namespace MyCoach.Services
{
  public interface IHomeService 
  {
    void ThisWeek(Action<HomeResponse> onSuccess, Action<HttpStatusCode> onFailure);
  }

  public class HomeService : BaseService, IHomeService
  {
    public HomeService(INetworkManager networkManager, IConfigurationService configurationService, ISettingsService settingsService, ICacheService cacheService)
        : base(networkManager, configurationService, settingsService, cacheService)
    {
    }

    public void ThisWeek(Action<HomeResponse> onSuccess, Action<HttpStatusCode> onFailure)
    {
        var request = RequestBuilder.GET("/home/thisweek", version: 2)
                                    .WithAccessToken(_settings)
                                    .Build();
        Execute(request, onSuccess, onFailure);
    }
  }
}

And here's my service where I see the strange debugger behavior:

namespace MyCoach.Services
{
    public interface IPingService
    {
        void PingValidEndpoint(Action<PingResponse> onSuccess, Action<HttpStatusCode> onFailure);
    }

    public class PingService : BaseService, IPingService
    {
        public PingService(INetworkManager networkManager, IConfigurationService configurationService, ISettingsService settingsService, ICacheService cacheService)
            : base(networkManager, configurationService, settingsService, cacheService)
        {
        }

        public void PingValidEndpoint(Action<PingResponse> onSuccess, Action<HttpStatusCode> onFailure)
        {
            var request = RequestBuilder.GET("/ping", version: 2)
                                        .WithAccessToken(_settings)
                                        .Build();
            Execute(request, onSuccess, onFailure);
        }
    }
}

What is the difference between those two services that is causing me to see the different behavior in the debugger?

DanHam
  • 340
  • 2
  • 17
  • 1
    Do you have [handled exception breaking](https://stackoverflow.com/questions/116896/visual-studio-how-to-break-on-handled-exceptions) enabled in Visual Studio? The exception handling block could itself throw an exception if the caught message does not contain a valid integer. Also, `ExecuteAsync` is asynchronous, but the call is not awaited in `Execute`. Async/await should bubble up the call stack (there's not really a point in having an `Execute` method, unless you call `Wait()` on the returned task). For debugging purposes, try calling `Wait()` on `ExecuteAsync` and see what pops up – Jonathan Tyson Aug 11 '17 at 00:47

1 Answers1

0

According to the HomeService and PingService class, they are implement the BaseService with the same way. So the problem should be related to the way that call them. Please check the code that you used to call PingService to make sure it use async and await to call the PingService. Detailed explanation and steps, please refer to following document.

https://msdn.microsoft.com/en-us/library/jj155813.aspx

Jack Zhai
  • 6,230
  • 1
  • 12
  • 20