Testing Relationships Between Entities


As was described previously, there is no enforcement of relationships in the typed DataSet . We made this decision to facilitate the separation of testing of individual entities from testing the relationships between entities. Without such separation, we would have to create an entire tree of related objects just to test one individual object in that tree. For example, if the relationship between the Review and Reviewer were enforced, we would have to create a Reviewer entity before we could test a Review entity, which would significantly complicate our test code. However, because the relationships are not enforced by the typed DataSet , we need to write tests to ensure that the relationships work as expected. We decided to organize these tests by having a separate test class for each relationship that exists in the schema. Because we are testing two related entities, we need to create both and build the relationship between the two after they are created. Let s begin by writing a test for the relationship between the Review and Reviewer entity.

ReviewReviewerFixture.cs

 using DataAccessLayer; using NUnit.Framework; [TestFixture] public class ReviewReviewerFixture : ConnectionFixture {    [Test]    public void ReviewerId()    {       RecordingDataSet recordingDataSet = new RecordingDataSet();       ReviewGateway reviewGateway = new ReviewGateway(Connection);       long reviewId =           reviewGateway.Insert(recordingDataSet, 1, "Review Content");              ReviewerGateway reviewerGateway =           new ReviewerGateway(Connection);       long reviewerId =           reviewerGateway.Insert(recordingDataSet, "Reviewer Name");       RecordingDataSet.Review review =           reviewGateway.FindById(reviewId, recordingDataSet);              review.ReviewerId = reviewerId;       reviewGateway.Update(recordingDataSet);       Assert.AreEqual(reviewerId, review.Reviewer.Id);       reviewGateway.Delete(recordingDataSet,reviewId);       reviewerGateway.Delete(recordingDataSet,reviewerId);    } } 

At first, the test inserts the two entities, Review and Reviewer , into the database. It then establishes the relationship between the entities. After the database is updated with the relationship, we test the ability to navigate from the Review to the Reviewer using the typed DataSet . After the test, we remove the test data from the database.

To complete the test list we need to write tests for the following relationships:

  • Track-Genre

  • Track-Artist

  • Recording-Label

  • Recording-Artist

  • Recording-Reviews

  • Review-Recording

We ll leave writing the tests for these relationships as an exercise for you because they are very similar to the ReviewReviewerFixture and they do not expose any additional design or implementation considerations.

Track-Recording Relationship

For the simpler entities such as Artist , it is simple to write the code to insert it into the database and remove it. That is not the case for Recording . The need to add the related objects significantly increases the amount of code that is needed to insert and remove the test data from the database. Because there is a lot of code and the need to have a test recording in multiple places, we will extract the insert/delete code from RecordingGatewayFixture and put it into its own class named RecordingBuilder .

 using System; using System.Data.SqlClient; using DataAccessLayer; public class RecordingBuilder {    private static readonly string title = "Title";    private static readonly DateTime releaseDate =        new DateTime(1999,1,12);        private long recordingId;    private long artistId;    private long labelId;    private RecordingGateway recordingGateway;    private ArtistGateway artistGateway;    private LabelGateway labelGateway;    public RecordingDataSet Make(SqlConnection connection)    {       RecordingDataSet recordingDataSet = new RecordingDataSet();       recordingGateway = new RecordingGateway(connection);       artistGateway = new ArtistGateway(connection);       labelGateway = new LabelGateway(connection);              artistId = artistGateway.Insert(recordingDataSet, "Artist");       labelId = labelGateway.Insert(recordingDataSet, "Label");       recordingId = recordingGateway.Insert(recordingDataSet,title,          releaseDate,artistId,labelId);       recordingGateway.FindById(recordingId, recordingDataSet);       return recordingDataSet;    }    public void Delete(RecordingDataSet dataSet)    {       artistGateway.Delete(dataSet,artistId);       labelGateway.Delete(dataSet,labelId);       recordingGateway.Delete(dataSet,recordingId);    }    #region properties    public long LabelId    { get { return labelId; } }    public long ArtistId    { get { return artistId; } }    public string Title    { get { return title; } }    public DateTime ReleaseDate    { get { return releaseDate; } }             public long RecordingId    { get { return recordingId; } }    public RecordingGateway RecordingGateway    { get { return recordingGateway; } }    #endregion } 

Separating this class from the test code makes the creation of a test recording much simpler. Similar to what we did previously to share the database connection, we can also create an abstract class named RecordingFixture whose responsibility is to insert a Recording entity into the database upon the call to SetUp and delete the Recording entity when TearDown is called.

 using DataAccessLayer; using NUnit.Framework; [TestFixture] public abstract class RecordingFixture : ConnectionFixture {    private RecordingBuilder builder = new RecordingBuilder();    private RecordingDataSet dataSet;    private RecordingDataSet.Recording recording;    [SetUp]    public void SetUp()    {       dataSet = builder.Make(Connection);       recording = dataSet.Recordings[0];    }    [TearDown]    public void TearDown()    { builder.Delete(dataSet); }    public RecordingBuilder Builder    { get { return builder; } }    public RecordingDataSet.Recording Recording    { get { return recording; } }    public RecordingDataSet RecordingDataSet    { get { return dataSet; } } } 

Finally, we will use the RecordingFixture in the TrackRecordingFixture to test the relationship between the Track and Recording entities:

 using DataAccessLayer; using NUnit.Framework; [TestFixture] public class TrackRecordingFixture : RecordingFixture {    private TrackGateway trackGateway;    private long trackId;    [SetUp]    public new void SetUp()    {       base.SetUp();       trackGateway = new TrackGateway(Connection);       trackId = trackGateway.Insert(RecordingDataSet, "Track", 120);       RecordingDataSet.Track track =           trackGateway.FindById(trackId, RecordingDataSet);       track.Recording = Recording;       trackGateway.Update(RecordingDataSet);    }    [TearDown]    public new void TearDown()    {       trackGateway.Delete(RecordingDataSet,trackId);       base.TearDown();    }    [Test]    public void Count()    {       Assert.AreEqual(1, Recording.GetTracks().Length);    }    [Test]    public void ParentId()    {       foreach(RecordingDataSet.Track track in Recording.GetTracks())       {          Assert.AreEqual(Recording.Id, track.RecordingId);       }    } } 

This test verifies that for each track present you can navigate back to its associated recording. The tests pass, so we have completed the testing of the relationships. Looking at the test list, we have only the tests left that retrieve the Recording and all of its associated entities by specifying the recording id. Let s do that and finish up.




Test-Driven Development in Microsoft .NET
Test-Driven Development in Microsoft .NET (Microsoft Professional)
ISBN: 0735619484
EAN: 2147483647
Year: 2004
Pages: 85

Similar book on Amazon

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net