I'm trying to create a fake repository for unit testing with a class object that has a one to many relationship. I'm using ASP.NET MVC and Linq to SQL. My reference is Steven Sanderson's "Pro ASP.NET MVC Framework" book.
I've created the Entity Classes with the association:
[Table(Name = "Albums")]
public class Album
{
[Column(IsDbGenerated = true, IsPrimaryKey = true)]
public int AlbumID { get; set; }
[Column]
public string Title { get; set; }
private EntitySet<Track> _tracks;
[Association(Storage = "_tracks", ThisKey = "AlbumID", OtherKey = "AlbumID")]
public EntitySet<Track> Tracks
{
get { return _tracks; }
set { _tracks.Assign(value); }
}
}
[Table(Name = "Tracks")]
public class Track
{
[Column(IsPrimaryKey = true)]
public int TrackID { get; set; }
[Column]
public string Title { get; set; }
[Column]
public int AlbumID { get; set; }
}
And an abstract interface for the repository:
public interface IMusicRepository
{
IQueryable<Album> Albums { get; }
IQueryable<Track> Tracks { get; }
}
I was able to create a fake repository for Albums - FakeMusicRepository:
public class FakeMusicRepository : IMusicRepository
{
private static IEnumerable<Track> fakeTracks = new List<Track>
{
new Track {AlbumID = 1, TrackID = 1, Title = "Flood"},
new Track {AlbumID = 1, TrackID = 2, Title = "Liquid"},
new Track {AlbumID = 2, TrackID = 1, Title = "Song 1"},
new Track {AlbumID = 2, TrackID = 2, Title = "Song 2"}
}.AsEnumerable();
private static IQueryable<Album> fakeAlbums = new List<Album>
{
new Album {AlbumID = 1, Title = "Jars of Clay"},
new Album {AlbumID = 2, Title = "Wind in the Wheat"}
}.AsQueryable();
public IQueryable<Album> Albums
{
get { return fakeAlbums; }
}
public IQueryable<Track> Tracks
{
get { return fakeTracks.AsQueryable(); }
}
}
Which works just fine as long as I don't try to access any tracks. In other words Album.Title works but accessing Album.Tracks.Count() will generate a null Reference exception. I wasn't sure if Linq-To-SQL or Linq-To-Objects would pickup the association and use it automatically with the fake objects or not.
The problem is that no matter what I try and can't seem to be able to assign the Tracks to Album class. I know that EntitySet is based on IEnumerable but it's been a challenge to cast the Enumerable list to a EntitySet.
Album is expecting an EntitySet but the only way I've been able to pass that in is via a custom helper:
public static class EntityCollectionHelper
{
public static EntitySet<T> ToEntitySet<T>(this IEnumerable<T> source) where T : class
{
EntitySet<T> set = new EntitySet<T>();
set.AddRange(source);
return set;
}
}
This is as close as I've come:
public class FakeMusicRepository2 : IMusicRepository
{
private static IEnumerable<Track> fakeTracks = new List<Track>
{
new Track {AlbumID = 1, TrackID = 1, Title = "Flood"},
new Track {AlbumID = 1, TrackID = 2, Title = "Liquid"},
new Track {AlbumID = 2, TrackID = 1, Title = "Song 1"},
new Track {AlbumID = 2, TrackID = 2, Title = "Song 2"}
}.AsEnumerable();
private static EntitySet<Track> Tracks1 = (from t in fakeTracks where t.AlbumID == 1 select t).ToEntitySet();
private static EntitySet<Track> Tracks2 = (from t in fakeTracks where t.AlbumID == 2 select t).ToEntitySet();
private static IQueryable<Album> fakeAlbums = new List<Album>
{
new Album {AlbumID = 1, Title = "Jars of Clay", Tracks=Tracks1},
new Album {AlbumID = 2, Title = "Wind in the Wheat", Tracks=Tracks2}
}.AsQueryable();
public IQueryable<Album> Albums
{
get { return fakeAlbums; }
}
public IQueryable<Track> Tracks
{
get { return fakeTracks.AsQueryable(); }
}
}
However when I try to access Album.Tracks I get
System.NullReferenceException : Object reference not set to an instance of an object.
Here is the implamentation / unit test:
[Test]
public void Test_FakeMusicRepository()
{
// Arrange: Setup Repository
var dc = new FakeMusicRepository2();
// Act:
var albums = dc.Albums.AsQueryable();
// Load the first test location
Album album = dc.Albums.First();
// Assert: That there are records in the Album Object
Assert.Greater(albums.Count(), 0, "No Albums Records Returned!");
//Assert that our first Album is not Null
Assert.IsNotNull(album, "returned Album is Null!");
// Assert: That we have the correct Album
Assert.AreEqual(album.AlbumID, 1, "Returned Album ID is not correct!");
// Try to Count the related sub table (Tracks)
var trackCount = album.Tracks.Count();
// Try to get the first Track
var track1 = album.Tracks.FirstOrDefault();
// Assert: The Album has Tracks
Assert.Greater(trackCount, 0, "Album has no Tracks");
// Assert: That First track is not Null
Assert.IsNotNull(track1, "Track1 object was Null!");
// Assert: That Track1 has data
Assert.IsNotNull(track1.TrackID, "Track1's ID was Null!");
}
I've spent days searching for an answer to this question and haven't found any examples so if someone would be able to post a working answer example I'm sure others would be interested as well.
I am very new to MVC and Unit Testing so please go easy with me. I have IoC and Moq on hand as well but I know even less about these but I'm planning on using both with this project. If there is a better way to do this then I'm all ears! Thanks.