fuaaark
fuaaark

Reputation: 551

Unit testing code using IQueryable

I'm asked to write some unit tests for some functionality, but quite frankly I'm not so sure about the need or usefulness of doing so for this particular piece of code. I'm in no way trying to question the need or usefulness of unit testing in general.

The code in question is very trivial and gets used alot. Basically it's a wrapper around the .Skip() and .Take() extension methods. In my opinion the legitimacy of the methods as a whole is questionable.

The code is basically this:

public IQueryable<T> Page(IQueryable<T> query, int page, int size)
{
    if(query == null) throw new ArgumentNullException("query");
    if(page < 0) throw new ArgumentOutOfRangeException("page"); 
    if(page < 0) throw new ArgumentOutOfRangeException("size"); 

    return query.Skip(page * size).Take(size);
}

Of course I can unit test for the expected exceptions, but what else? Could very well be that I'm missing the point, so what's up with this?

Upvotes: 3

Views: 5011

Answers (4)

Daniel Hilgarth
Daniel Hilgarth

Reputation: 174379

You can test quite a few things here:

  1. Check for proper guards (the exceptions that are thrown when invalid parameters are passed).
  2. Check that Skip was called with the correct parameter.
  3. Check that Take was called with the correct parameter.
  4. Check that Skip was called before Take.

Points 2 - 4 are best tested with a mock. A mocking framework comes in handy here.
This kind of testing is called "interaction-based testing".

You could also use "state-based testing" by calling the method under test with a list with data and check that the returned data is the correct subset.

A test for point 2 could look like this:

public void PageSkipsThePagesBeforeTheRequestedPage()
{
    var sut = new YourClass();
    var queryable = Substitute.For<IQueryable<int>>();

    sut.Page(queryable, 10, 50);

    queryable.Received().Skip(500);
}

This test uses NSubstitute as mocking framework.

Upvotes: 2

Mat&#237;as Fidemraizer
Mat&#237;as Fidemraizer

Reputation: 64943

In fact, since IQueryable<T> may encapsulate an underlying data storage - which is the case of Entity Framework's queryables -, we're talking about integration tests.

In my case, if I'd need to test something like your piece of code, I'd store some test data in the database for later query for it.

Since I can expect the results, I can perform an assertion in order to check if the tested method returned the expected result.

UPDATE

Since I see some confusion with the downvote and some comments, I'd like to point out that I've answered this taking in account the fact that the answer is tagged as for Entity Framework and I guess that the queryable was obtained from the DbSet.

Upvotes: 0

Mikhail
Mikhail

Reputation: 898

I'm sure, there is a strong need to test this method. First of all, because of the bug:

if(page < 0) throw new ArgumentOutOfRangeException("page"); 
if(page < 0) throw new ArgumentOutOfRangeException("size"); 

You're not checking the size variable in fact.

Anyway, there is no need to perform the "integrated" testing - you can simply mock your IQueryable object and perform the unit testing. (see this answer: How do I mock IQueryable<T>) In my opinion, it is an absolutely right thing to do to test this method.

Upvotes: 0

vcsjones
vcsjones

Reputation: 141668

You can just hand in a static collection by calling AsQueryable

List<T> dummyData = new List<T>();
//Add data
var result = Page(dummyData.AsQueryable(), 0, 10);
//Perform assertions on result.

If you are in-fact just trying to test that your pagination works correctly.

Upvotes: 4

Related Questions