Now that I've got my data context class set up, I need a repository for at least basic CRUD operations for my Location
class. In order to test this, I create a new test project. In the UnitTestApp.xaml.cs file, I add the following code to the constructor:
using (var db = new QuesterContext())
{
db.Database.Migrate();
}
This is to apply any pending migrations before running any of the tests.
Next, the beginning of my LocationRepository
class:
public class LocationRepository
{
public IEnumerable<Location> Get()
{
return null;
}
}
This simply returns null
to give me my first red test.
In my first test, I'll try to read from an empty table, so I have to clear all entries from it first. After all, I can't be sure that this test won't run after one that adds something to my Locations
table.
[TestMethod]
public void Get_returns_an_empty_set_if_table_contains_no_entries()
{
QuesterContext dbcontext = new QuesterContext();
dbcontext.RemoveRange(dbcontext.Locations);
dbcontext.SaveChanges();
LocationRepository locationRepository = new LocationRepository();
var locations = locationRepository.Get().ToList();
Assert.AreEqual(0, locations.Count);
}
Running the test gives me a red result, as I expected, so now I add the functionality I want to my Get()
method:
public class LocationRepository
{
public IEnumerable<location> Get()
{
IEnumerable<location> result = null;
using (QuesterContext context = new QuesterContext())
{
result = from e in context.Locations
select e;
}
return result;
}
}
I run my test again and... Gadzooks! It's still red! Looking at the test results, I see the following message: "System.ObjectDisposedException: Cannot access a disposed object.
"
Well, that's because I forgot that my LINQ query actually uses lazy evaluation, and by the time I get around to trying to use my result (in my test), my database context has already disposed of. So I do a quick fix on my Get()
method to force the evaluation of my query while it's still in scope:
public IEnumerable<location> Get()
{
IEnumerable<location> result = null;
using (QuesterContext context = new QuesterContext())
{
result = (from e in context.Locations
select e).ToList();
}
return result;
}
...and running this give me the first green test for my repository class. So there it is - the test did its job to point out my temporary lapse of memory. Good test. Have a biscuit.
Now let's see how we fare with a table that's not empty:
[TestMethod]
public void Get_returns_all_stored_locations()
{
Location l1 = new Location(4);
Location l2 = new Location(2);
Location l3 = new Location(7);
QuesterContext dbcontext = new QuesterContext();
dbcontext.RemoveRange(dbcontext.Locations);
dbcontext.Locations.Add(l1);
dbcontext.Locations.Add(l2);
dbcontext.Locations.Add(l3);
dbcontext.SaveChanges();
LocationRepository locationRepository = new LocationRepository();
var locations = locationRepository.Get().ToList();
Assert.AreEqual(3, locations.Count);
}
This test returns green straight away. I have no idea how I could make it red. I guess I should have created it at the same time as the first test, since it tests the same method. Ah, well, live and learn...
P.S. Remember: this is NOT a tutorial on how to write good code. This is an exploration of how useful TDD is in weeding out mistakes, bad code and possibly bad architecture. So I'm throwing everything at it, including the kitchen sink.
P.P.S. You may be able to see where this is going. I'm currently looking at the code I will be using over the next few posts, and I'm not certain if the wetness trickling down my face is tears or if my eyes are bleeding.
P.P.P.S But hey - "For Science!"CodeProject