1
\$\begingroup\$

I'm writing wrapper for REST API of a service. In my wrapper I have quite simple method:

public List<string> GetAvailableSources()
{
    var request = new RestRequest($"session/{Id}");
    var sessionProto = _client.Execute<SessionPrototype>(request);
    return sessionProto.Data.InstalledSources;
}

It's really simple and just sends request to service and returns result. However, unit test for that method is huge:

[Test]
public void GetAvailableSources_MustReturnItemsFromResponse()
{
    const long sessionId = 123;

    var clientMock = new Mock<IRestClient>();

    clientMock.Setup(x => x.Execute<SessionPrototype>(It.IsAny<IRestRequest>()))
        .Returns(new RestResponse<SessionPrototype>()
        {
            Data = new SessionPrototype
            {
                Id = sessionId,
                InstalledSources = new List<string>
                {
                    "Scanner1",
                    "Scanner2"
                }
            },
            StatusCode = HttpStatusCode.OK
        }).Verifiable();

    var session = new Session(sessionId, clientMock.Object);
    var sources = session.GetAvailableSources();
    Assert.That(sources, Has.Count.EqualTo(2));
    Assert.That(sources[0], Is.EqualTo("Scanner1"));
    Assert.That(sources[1], Is.EqualTo("Scanner2"));
    clientMock.Verify(
        m => m.Execute<SessionPrototype>(
            It.Is<IRestRequest>(
                r => r.Resource == $"session/{sessionId}" && r.Method == Method.GET)));
}

Is there a way for simplifying tests for REST API?

\$\endgroup\$

1 Answer 1

1
\$\begingroup\$

You could simplify entire test class by extracting part responsible for general configuration. Then you can easili split your test into two, first verifying that your IRestClient is properly called during the process and second that assures tested method returns result provided by this client. For tests that require specific configuration, like throwing exceptions and so on, I found it a nice way to extract this configuration to separate, private methods and calling them when necessary instead of configuring all the scenarios in the Setup method.

[TestFixture]
public class ClientTest
{
    private const long SessionId = 123;
    private Mock<IRestClient> _clientMock;
    private List<string> _expectedSources;
    private Session _session;

    [SetUp]
    public void Setup()
    {
        _expectedSources = new List<string>
                {
                    "Scanner1",
                    "Scanner2"
                };
        _clientMock = new Mock<IRestClient>();
        _clientMock.Setup(x => x.Execute<SessionPrototype>(It.IsAny<IRestRequest>()))
                   .Returns(new RestResponse<SessionPrototype>()
        {
            Data = new SessionPrototype
            {
                Id = SessionId,
                InstalledSources = _expectedSources
            },
            StatusCode = HttpStatusCode.OK
        }).Verifiable();

        _session = new Session(SessionId, _clientMock.Object);
    }

    [Test]
    public void GetAvailableSources_MustCallTheClientUsingProperRequest()
    {
        _clientMock.Verify(
            m => m.Execute<SessionPrototype>(
                It.Is<IRestRequest>(
                r => r.Resource == $"session/{SessionId}" && 
                     r.Method == Method.GET)));
    }

    [Test]
    public void GetAvailableSources_ReturnsSourcesProvidedByClient()
    {
        var sources = _session.GetAvailableSources();

        CollectionAssert.AreEquivalent(_expectedSources, sources);
    }
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.