refit and unittests

Created on 8 Jan 2015  路  6Comments  路  Source: reactiveui/refit

Does refit support request stubbing? I would like to test written apis without the need to send a real request.

outdated

Most helpful comment

Found a solution using Nunit and MockHttp. Here is a dummy implementation:

namespace RebuySdk.Tests
{
    [TestFixture]
    public class Test
    {
        [Test]
        public async void TestCase()
        {
            using (FileStream fs = File.OpenRead("../../test.json")) {

                var mockHttp = new MockHttpMessageHandler();
                mockHttp.When("http://localhost/*").Respond("application/json", fs);

                var client = new HttpClient(mockHttp) {
                    BaseAddress = new Uri("http://localhost"),
                };

                var api = RestService.For<ISolrApi>(client);
                var response = await api.Search("hi there");
            }
        }
    }
}

All 6 comments

Found a solution using Nunit and MockHttp. Here is a dummy implementation:

namespace RebuySdk.Tests
{
    [TestFixture]
    public class Test
    {
        [Test]
        public async void TestCase()
        {
            using (FileStream fs = File.OpenRead("../../test.json")) {

                var mockHttp = new MockHttpMessageHandler();
                mockHttp.When("http://localhost/*").Respond("application/json", fs);

                var client = new HttpClient(mockHttp) {
                    BaseAddress = new Uri("http://localhost"),
                };

                var api = RestService.For<ISolrApi>(client);
                var response = await api.Search("hi there");
            }
        }
    }
}

@omares Refit interfaces are Just Interfaces, you can use any mock framework you want to stub them, you don't need to create custom HttpClients:

public interface IGitHubApi
{
    [Get("/users/{user}")]
    Task<User> GetUser(string user);
}

Then, in a different part of town:

var fakeGitHub = Substitute.For<IGitHubApi>();
MyMethodToTest(fakeGitHub);

Ah! Having a documentation for the Substitute class would be nice :) Also mocking the http requests enabled me to create the DTO classes without the need for a working endpoint. It is a different use case, maybe not that often needed but i still think it should be noted somewhere.

NSubstitute is a separate library, check it out here: http://nsubstitute.github.io/

What would a test look like using here?

@kfrancis You probably aren't interested anymore. But I came across this issue when searching for information on unit testing with Refit. Here's some sample code so others can get an idea of how simple it is to unit test with Refit.

For reference, I'm using xUnit, NSubstitute, and Shouldly for my unit test project.

// Unit Test
[Fact]
public async Task Authenticate_InvalidCredentials_ShouldReturnFalse()
{
    var exception = await ApiException.Create(
        new HttpRequestMessage(),
        HttpMethod.Get,
        new HttpResponseMessage(HttpStatusCode.Unauthorized));

    var myRestApi = Substitute.For<IMyRestApi>();
    myRestApi.GetSubscriptions(Arg.Any<string>()).Throws(exception);

    var sut = new ApiService(myRestApi);

    var result = await sut.Authenticate("username", "password");

    result.ShouldBeFalse();
}

// Refit Interface
[Headers("Accept: application/xml")]
public interface IMyRestApi
{
    [Get("/subscription")]
    Task<SubscriptionsResponse> GetSubscriptions([Header("Authorization")] string authorization);
}

// Class that consumes Refit interface
public class ApiService : IApiService
{
    private readonly IMyRestApi _api;

    public ApiService(IMyRestApi api)
    {
        _api = api;
    }

    public async Task<bool> Authenticate(string username, string password)
    {
        var authHeader = CreateAuthenticationHeader(username, password);

        try
        {
            await _api.GetSubscriptions(authHeader);
        }
        catch (ApiException ex)
        {
            if (ex.StatusCode == HttpStatusCode.Unauthorized)
            {
                return false;
            }

            throw;
        }

        return true;
    }

    private string CreateAuthenticationHeader(string username, string password)
    {
        var encodedCredentials = Convert.ToBase64String(Encoding.ASCII.GetBytes($"{username}:{password}"));

        return $"Basic {encodedCredentials}";
    }
}
Was this page helpful?
0 / 5 - 0 ratings

Related issues

jamiehowarth0 picture jamiehowarth0  路  5Comments

jstafford5380 picture jstafford5380  路  4Comments

AnjaliSahu51 picture AnjaliSahu51  路  4Comments

ColKrumpler picture ColKrumpler  路  3Comments

tstivers1990 picture tstivers1990  路  5Comments