Strawberry
Strawberry

Reputation: 119

Nsubstitute set return value with Generic Repository

I have a generic repository for MongoDB.

This is my Get method:

public IList<TEntity> Get<TEntity>(System.Linq.Expressions.Expression<Func<TEntity, bool>> filter = null) where TEntity : class, new()
{
    var collection = GetCollection<TEntity>();

    var query = Query<TEntity>.Where(filter);
    var entity = collection.FindAs<TEntity>(query).ToList();

    return entity;
}

When I try to mock it, I get an error:

IList<Login> (where Login is my business object) does not contain any a definition for ReturnsForAnyArgs.

[TestMethod]
public void CheckIfUserNameExits_IfUserNameDoesNotExist_ReturnFalse()
{
    Login login = null;
    Task<IList<Login>> logl = null;
    // _mongoDAL.Get<Arg.Any<Login>()>(Arg.Any<Expression<Func<TEntity, bool>>>).ReturnsForAnyArgs
    //_mongoDAL.When(x => x.Get<Login>(Arg.Any<Expression<Func<Login, bool>>>())).ReturnsForAnyArgs(logl);
    _mongoDAL.Get<Login>(Arg.Any<Expression<Func<Login, bool>>>()).ReturnsForAnyArgs(logl);
}

Any suggestions on how to mock it, so that I can set the return value I want in my unit test?

Upvotes: 1

Views: 2147

Answers (2)

Strawberry
Strawberry

Reputation: 119

Solved it.

var loginList = new List<Login>();
_mongoDAL.Get<Login>(Arg.Any<Expression<Func<Login, bool>>>()).Returns(loginList);

Don't know why with just Returns, it works.

Upvotes: 1

forsvarir
forsvarir

Reputation: 10839

The issue is caused by you passing the wrong type to your ReturnsForAnyArgs call. This behaviour is the same, if you are calling Returns, or ReturnsForAnyArgs.

Your Get method is defined as returning IList<TEntity>. In your initial question you are returning logl, which is of type Task<IList<Login>> (notice the Task wrapping your IList). In your solution however, you are instead passing loginList, which is a List<T>, which implements IList<T> hence your code compiles. So, as an alternate, you could have used:

_mongoDAL.Get<Login>(Arg.Any<Expression<Func<Login, bool>>>())
         .ReturnsForAnyArgs(loginList);

The compilation error you get initially is a bit cryptic. The full error message is:

error CS1928: 'System.Collections.Generic.IList' does not contain a definition for 'ReturnsForAnyArgs' and the best extension method overload 'NSubstitute.SubstituteExtensions.ReturnsForAnyArgs(System.Threading.Tasks.Task, T, params T[])' has some invalid arguments

The first half of the error message looks like it's pointing to a missing extension method. However, in reality the problem is that it's failing to match to any of the overloaded methods and so it's picking the closest and showing you how it doesn't match.

Typically you'll get a second error that will help to indicate that this is your problem. Something like this:

error CS1929: Instance argument: cannot convert from 'System.Collections.Generic.IList' to 'System.Threading.Tasks.Task>>'

Upvotes: 0

Related Questions