Question

I´m trying to substitute the call Any() of an IDBSet<T> with NSubstitute but the test fails with an ArgumentNullException

Test Name: TestMethod1 Test FullName: Clientmanagement.Tests.UnitTest1.TestMethod1 Test Source: c:\develop\Clientmanagement\Clientmanagement.Tests\UnitTest1.cs : line 12 Test Outcome: Failed Test Duration: 0:00:00.3701927

Result Message: Test method Clientmanagement.Tests.UnitTest1.TestMethod1 threw exception: System.ArgumentNullException: Value cannot be null. Parameter name: arguments Result StackTrace: at System.Linq.Expressions.Expression.RequiresCanRead(Expression expression, String paramName) at System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase method, ExpressionType nodeKind, Expression arg, ParameterInfo pi)
at System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase method, ExpressionType nodeKind, ReadOnlyCollection1& arguments)
at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable
1 arguments) at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, Expression[] arguments) at System.Linq.Queryable.Any[TSource](IQueryable1 source, Expression1 predicate) at Clientmanagement.Tests.UnitTest1.TestMethod1() in c:\develop\Clientmanagement\Clientmanagement.Tests\UnitTest1.cs:line 19

Here is how my Test method looks like

public void EnsureThatIdentifierIsUnique() {
  IClientContext context = Substitute.For<IClientContext>();

  IDbSet<Client> clients = Substitute.For<IDbSet<Client>>();

  context.Clients.Returns(clients);

  clients.Any(p=>p.Identifier == "Test").Returns(true);  // this line throws the exception

  ClientService service = new ClientService(context);

  service.CreateClient("Test");
}

Now my question is if it is possible to substitute the methods of IQueryable with NSubstitute? Is the setup of my test method wrong?

Was it helpful?

Solution

Now my question is if it is possible to substitute the methods of IQueryable with NSubstitute?

Any isn't a method on IQueryable. It's an extension method - a static method which is called as if it were an instance method. So unless NSubstitute can mock out static methods somehow (like Typemock Isolator does), you're going to have problems.

A really smart LINQ-oriented mocking system could essentially provide fake information to Queryable and respond to similar expression trees when it was given them by the production code - but it would be very fragile. You'd be better off with an in-memory database if at all possible.

In general, you shouldn't rely on your production code making an exact sequence of calls if another sequence would be equivalent. For example, it would be reasonable for your production code to be written as

clients.Where(p=>p.Identifier == "Test").Any()

it's not as readable, but it's fundamentally equivalent to the call to Any with a predicate. Your test should be able what the production code achieves, not the exact steps it takes to achieve it.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top