TheErikPowell
TheErikPowell

Reputation: 85

NSubstitute returns first InlineData value for all tests

I am relatively new to testing. We use XUnit and NSubstitute as our testing frameworks and I am having trouble with what should be a simple test. I am using a Class library to interact with an external api and I need to be able to determine if the api is available before performing operations. (I should mention that the dll already works. We are retroactively adding tests.)

The problem I am encountering is that no matter what the InlineData is for the test, the substitute (client.Execute...) only ever returns the value for the first InlineData value. If the first value is HttpStatusCode.OK, then other InlineData values fail the test because the substitute only returns HttpStatusCode.OK. If I swap OK with Forbidden, then the HttpStatusCode.OK fails because the substitute only ever returns Forbidden as the StatusCode.

I could break these out into separate tests, but I would prefer to understand the behavior before doing so.

The Test

[Theory]
[InlineData(HttpStatusCode.OK)]
[InlineData(HttpStatusCode.Forbidden)]
[InlineData(HttpStatusCode.BadRequest)]
[InlineData(HttpStatusCode.NotFound)]
public void ConnectionCheck(HttpStatusCode code)
{
    var d2lClient = new d2lClient("userid", "userkey", "mappid", "mappkey", "serviceurl.com", "1");
    var client = Substitute.For<IRestClient>();
    var authenticator = Substitute.For<iITGValenceAuthenticator>();

    client.Execute<WhoAmIUser>(Arg.Any<IRestRequest>()).ReturnsForAnyArgs(x => new RestResponse<WhoAmIUser>()
        {
            StatusCode = code
        });


    d2lClient.GetOrCreateRestClient(client);
    d2lClient.GetOrCreateAuthenticator(authenticator);

    if (code == HttpStatusCode.OK)
    {
        Assert.True(d2lClient.ConnectionCheck(), "client.ConnectionCheck() should be true for " + code);
    }
    else
    {
        Assert.False(d2lClient.ConnectionCheck(), "client.ConnectionCheck() should be false for " + code);
    }
}

The Method

public bool ConnectionCheck()
{
    if (_userId == null || _userKey == null || _mAppId == null || _mAppKey == null)
        return false;

    try
    {
        var response = GetRestResponse<WhoAmIUser>(_userId, _userKey, d2lRoute.WhoAmI());

        return response.StatusCode == HttpStatusCode.OK;
    }
    catch (Exception ex)
    {
        return false;
    }
}

public IRestResponse<T> GetRestResponse<T>(string userId, string userKey, string url, List<Parameter> parameters = null, IRestRequest request = null, IRestClient client = null, iITGValenceAuthenticator authenticator = null) where T : new()
{
    /*
       Irrelevant code
    */
    return _client.Execute<T>(request);
}

Upvotes: 0

Views: 635

Answers (1)

TheErikPowell
TheErikPowell

Reputation: 85

Thanks to David Tchepak for the help! I took his example and modified it a bit more to match the structure of the code. When I did that and it worked, it became clear something was wrong with my class library. Turns out, _client had inadvertently been marked as static. This didn't matter until we wanted to test it and I had to pull out the client creation to allow for dependency injection. Previously, the client had been a local variable for each api call.

Once the static modifier was removed from the _client property, the tests functioned as expected.

Changed

private static IRestClient _client;
private static IRestRequest _request;

to

private IRestClient _client;
private IRestRequest _request;

in the d2lClient class.

Upvotes: 1

Related Questions