I am trying to mock a repository that inherits from the BaseRepository class in the Ardalis.Specification.EntityFrameworkCore library. This base class exposes the ListAsync method which takes in a subclass of the Specification class.

This is one of those specifications I have built:

public sealed class SomeSpecification: Specification<SomeEntity>
{
    public SomeSpecification(Guid someSubEntityID)
    {
        Query
            .Include(p => p.SomeSubEntity)
            .Where(p => p.SomeSubEntity.Id == someSubEntityID)

            .Include(p => p.SomeOtherSubEntity)

            .OrderBy(p => p.SomeProperty);
    }
}

When writing unit tests, I am trying to configure a mock for my ISomeEntityRepository for this specific method using this specification class. What I want is to be able to return a specific collection when this method is passed any SomeSpecification object that was built using a SPECIFIC guid. As you see, the id that is passed to this constructor is not store anywhere in the class as a property or field when constructing it.

What I can do is something like this where the method just returns a specific collection I'm storing in an EntityConstants class when any SomeSpecification is passed:

_pfRepoMock.ListAsync(
    Arg.Any<SomeSpecification>(), Arg.Any<CancellationToken>())
    .Returns(Task.FromResult(EntityConstants.SomeEntityCollection()));

This works fine but I'm not able to return 2 different collections depending on what guid was passed to the SomeSpecification constructor. In my ideal world, what I'd like to be able to do, is something like this:

_pfRepoMock.ListAsync(
    Arg.Any<SomeSpecification>().ConstructedWith(EntityConstants.SomeID), Arg.Any<CancellationToken>())
    .Returns(Task.FromResult(EntityConstants.SomeEntityCollection()));

_pfRepoMock.ListAsync(
    Arg.Any<SomeSpecification>().ConstructedWith(EntityConstants.SomeOtherID), Arg.Any<CancellationToken>())
    .Returns(Task.FromResult(EntityConstants.SomeDifferentEntityCollection()));

I know there is an NSubstitute.Equivalency library that adds an ArgEx class but I can't see how it can accomplish what I want.

How can I achieve this?

1 Reply 1

I was trying to avoid having to edit my specifications to store the Id in a property but that does indeed work. However, the API for the Ardalis library might have changed since there is no Criteria property in the spec object. It does have a WhereExpressions collection with one entry but nowhere in there do I find a textual representation of my Guid.

Your Reply

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.