Everything I've read so far suggests that creating a functional mock of an IDataReader
is going to be at least as complex as the code you're testing, probably more so.
My recommendation would be to write an integration test, not a unit test. I typically have some helper methods in my test project that insert the records I'm expecting in my development database so that I know exactly what the test should return. After executing the test I clear out the test data.
This blog post describes it in some more detail.
For this sort of operation I trust it a lot more than a mock, because it's testing the database and my stored procedure. It's not as granular as a unit test but it serves the same purpose. If there are defects in either the stored procedure or the code that reads from it I'm going to find them easily and fix them.
I've read a number of recommendations that for some operations integration testing is more practical than unit testing (unless you can do both.) This looks like one of those cases. All the code I've seen for mocking IDataReader
looks very complicated and it ends up being too different from the reality that you're testing.
In my sample code in the blog post I'm using a class to insert data and then testing to ensure that a SELECT
returns the expected data.
For testing a class that reads data I'd do the opposite.
- Write a method in the integration test that "arranges" by inserting some test data. I usually put something in at least one of the columns like a particular string or number so that after the test I can delete exactly those records.
- "Act" - call the method I'm testing and have it read from the database. This typically returns some collection of objects.
- "Assert" that the properties of the objects returned match the values I inserted.