Search code examples
c#moqidentityserver4marten

Unit Testing Marten


I'm putting together an implementation of IdentityServer4, using PostgreSQL as the database, Marten as the ORM, and GraphQL as the API. So far, it's working great at runtime. However, I'm also trying to get unit tests in place, and am running into an issue. I have a custom implementation of IdentityServer4's IClientStore interface, where the implementation of the FindClientByIdAsync method looks thus:

public async Task<Client> FindClientByIdAsync(string clientId)
{
    var client = await _documentSession.Query<dbe.Client>().FirstOrDefaultAsync(c => c.ClientId == clientId);
    return _mapper.Map<Client>(client); // AutoMapper conversion call
}

This works great at runtime. However, I have the following test that I'm trying to put in place to exorcise this code:

[Fact]
public async Task FindClientByIdReturnsClient()
{
    var clients = new []
    {
        new dbe.Client
        {
            ClientId = "123"
        }
    }.AsQueryable();

    var queryable = new MartenQueryable<dbe.Client>(clients.Provider);
    // _documentSession is a Moq Mock
    _documentSession.Setup(x => x.Query<dbe.Client>()).Returns(queryable);

    var store = new ClientStore(_documentSession.Object, _mapper);

    var result = await store.FindClientByIdAsync("123");

    Assert.NotNull(result);
    Assert.Equal("123", result.ClientId);
}

The error I get happens when the test tries to execute the FindClientByIdAsync method:

System.InvalidCastException : Unable to cast object of type 'System.Linq.EnumerableQuery`1[StaticSphere.Persona.Data.Entities.Client]' to type 'Marten.Linq.IMartenQueryable'.

If anyone is familiar with Marten can could provide some insight, that would be great! I've done my Google time, and haven't found anything concrete on the subject.


Solution

  • A quote from the creator of Marten which could be relevant here (context):

    You can mock a bit of IDocumentSession (Load, Store, SaveChanges, maybe query by compiled query), but you’re gonna be in a world of hurt if you try to mock the Linq support.

    So one solution would be to do integration tests for which you can find some code from the official Marten's repository or here.