rosalindwills
rosalindwills

Reputation: 1474

How to unit test methods using Neo4JClient

I have been working on implementing a .NET Core API using Neo4J as the data storage and Neo4JClient (https://github.com/Readify/Neo4jClient) to build the data layer of the application. Things are going pretty well but I'm at a loss for strategies on how to test methods using the client in a way that adequately verifies that the code is doing what it's expected to do.

Example method using Neo4JClient:

private readonly IGraphClient _graphClient;
protected IGraphClient GraphClient => _graphClient;

public BaseRepository(GraphClient client)
{
    _graphClient = client;
    _graphClient.Connect();
}

public async Task<IList<TModel>> GetAllAsync()
{
    var results = await GraphClient.Cypher.Match($"(e:{typeof(TModel).Name})")
        .Return(e => e.As<TModel>())
        .ResultsAsync;
    return results.ToList();
}

Is there existing documentation for mocking and unit testing methods that operate on the GraphClient like this? I haven't been able to find anything in Google searches on the subject.

Upvotes: 0

Views: 790

Answers (1)

Creyke
Creyke

Reputation: 2107

Fluent APIs seem like such a good idea until someone wants to mock them.

However, at least the Neo4JClient graph client is based off interfaces.

You could do something like this (you'll need to change your constructor argument to be an IGraphClient instead of a GraphClient.

public class BaseRepositoryTests
{
    private readonly BaseRepository<Model> subject;
    private readonly Mock<ICypherFluentQuery> mockCypher;
    private readonly Mock<ICypherFluentQuery> mockMatch;
    private readonly Mock<IGraphClient> mockGraphClient;

    public BaseRepositoryTests()
    {
        mockMatch = new Mock<ICypherFluentQuery>();

        mockCypher = new Mock<ICypherFluentQuery>();
        mockCypher
            .Setup(x => x.Match(It.IsAny<string[]>()))
            .Returns(mockMatch.Object);

        mockGraphClient = new Mock<IGraphClient>();
        mockGraphClient
            .Setup(x => x.Cypher)
            .Returns(mockCypher.Object);

        subject = new BaseRepository<Model>(mockGraphClient.Object);
    }

    [Fact]
    public async Task CanGetAll()
    {
        IEnumerable<Model> mockReturnsResult = new List<Model> { new Model() };

        var mockReturn = new Mock<ICypherFluentQuery<Model>>();

        mockMatch
            .Setup(x => x.Return(It.IsAny<Expression<Func<ICypherResultItem, Model>>>()))
            .Returns(mockReturn.Object);

        mockReturn
            .Setup(x => x.ResultsAsync)
            .Returns(Task.FromResult(mockReturnsResult));

        var result = await subject.GetAllAsync();

        Assert.Single(result);
    }

    public class Model { }
}

Upvotes: 1

Related Questions