Image Image Image Image Image
Scroll to Top

To Top

Clean Code Developer Here I share my ideas about software craftsmanship.

Walkthrough: ADO.NET Unit Testable Repository Generator

On 27, Okt 2010 | inClean Code Developer | vonJohannes Hoppe

This walkthrough is going to show you the usage of my new T4 template called „ADO.NET Unit Testable Repository Generator“.

Table of contents:

My demo implements a small repository to manage simple text-snippeds in the database. I will start with an empty ASP.NET MVC 2 project. Any other type would work, too.


Step 1: Create the Entity Data Model

Now we are going to add an Entity Data Model (EDMX) file.

  • Right click on Models, select Add > New Item…
  • and choose ADO.NET Entity Data Model. I recommend the Name: “WebNoteModel.edmx

  • Generate it from the database,

  • and create a working connection string with the help of the wizard.
  • Please be sure that you select a meaningful Entity Container Name. This name will be used for the generated files, too. I chose “FileStore”.

  • Select your tables and Pluralize or singularize generated object names (select the checkbox)
  • and chose a name for the Namespace. In my case: „WebNoteModelDatabase“.

Step 2: Add the Code Generation Item

All right. This was standard stuff. We are now going to include the T4 template.

  • Open the created EDMX file, right click the background, and from the context menu select Add Code Generation Item and chose the item “ADO.NET Unit Testable Repository Generator”. You could use the name “WebNoteModel.tt” here. (Note: the screenshot is outdated, I renamed the extension. The previous name was: „ADO.NET Mocking Context Generator – Extended“)

  • The T4 templates have generated some new files. This includes all the required POCOs (Plain Old CLR Object), a simple ObjectContext and an Interface that should be used to access it. If you get compilation errors, then you should reference the following assemblies:
    1. Microsoft.Practices.Unity (download at http://unity.codeplex.com)
    2. Microsoft.VisualStudio.QualityTools.UnitTestFramework (included with Visual Studio)

Step 3: Use the Repository

To start coding you just have to create a partial class with the name of the entity container and the suffix “Repository”. (eg. “public partial class WebNoteRepository”). The following sample shows all CRUD (Create, Read, Update and Delete) operations on the Entity “Note”.

namespace WebNoteMvc.Models
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
 
    /// <summary>
    /// Sample Repository
    /// </summary>
    public partial class WebNoteRepository
    {
        /// <summary>
        /// Gets all notes from DB
        /// </summary>
        /// <returns>all notes from DB</returns>
        public IEnumerable<Note> GetAllNotes()
        {
            return this.Context.Notes.ToList();
        }
 
        /// <summary>
        /// Gets one note from DB
        /// </summary>
        /// <param name="id">The id of the note to show.</param>
        /// <returns>notes from DB</returns>
        public Note GetNote(int id)
        {
            Note noteToShow = (from n in this.Context.Notes
                               where n.NoteId == id
                               select n).FirstOrDefault();
 
            return noteToShow;
        }
 
        /// <summary>
        /// Adds the a new note to DB.
        /// </summary>
        /// <param name="noteToAdd">The note to add.</param>
        public void AddNote(Note noteToAdd)
        {
            noteToAdd.Added = DateTime.Now;
            this.Context.Notes.AddObject(noteToAdd);
            this.Context.SaveChanges();
        }
 
        /// <summary>
        /// Edits one note note.
        /// </summary>
        /// <param name="noteData">note data.</param>
        public void EditNote(Note noteData)
        {
            Note noteToEdit = this.GetNote(noteData.NoteId);
 
            if (noteToEdit == null)
            {
                return;
            }
 
            noteToEdit.Title = noteData.Title;
            noteToEdit.Message = noteData.Message;
            this.Context.SaveChanges();
        }
 
        /// <summary>
        /// Deletes one note note.
        /// </summary>
        /// <param name="id">The id of the note to delete.</param>
        public void DeleteNote(int id)
        {
            Note noteToDelete = this.GetNote(id);
 
            if (noteToDelete == null)
            {
                return;
            }
 
            this.Context.Notes.DeleteObject(noteToDelete);
            this.Context.SaveChanges();
        }
    }
}

Step 4: Use the unit test

The following example shows a simple unit test. The T4 template has generated a base class for you. You just have to inherit from the XBaseRepository-class. The class requires you to implement the abstract methods that should return a list of Entities. These Entities “simulate” a real database.

namespace WebNoteMvc.Tests.Models
{
    using System;
    using System.Collections.Generic;
    using System.Globalization;
    using System.Linq;
 
    using Microsoft.VisualStudio.TestTools.UnitTesting;
 
    using NUnit.Framework;
 
    using WebNoteMvc.Models;
    using WebNoteMvc.Models.WebNoteUnitTest;
 
    using Assert = NUnit.Framework.Assert;
    using IgnoreAttribute = Microsoft.VisualStudio.TestTools.UnitTesting.IgnoreAttribute;
 
    /// <summary>
    /// Example test for the WebNoteRepository
    /// </summary>
    [TestClass]
    public class WebNoteRepositoryTest : WebNoteBaseRepositoryTest
    {
        [TestMethod]
        public void GetAllNotesTest()
        {
            // Arrange
            IEnumerable<Note> expected = this.CreateNotesList();
 
            // Act
            IEnumerable<Note> actual = Repository.GetAllNotes();
 
            // Assert
            Assert.That(actual, Is.EquivalentTo(expected));
        }
 
        [TestMethod]
        public void AddNoteTest()
        {
            // Arrange
            int countBefore = this.Context.Notes.Count();
 
            // Act
            Repository.AddNote(new Note());
            int countAfter = this.Context.Notes.Count();
 
            // Assert
            Assert.That(countBefore + 1, Is.EqualTo(countAfter));
            Assert.That(this.Context.SavesChanged);
        }
 
        [TestMethod]
        public void EditNoteTest()
        {
            // Arrange
            Note noteToChange = new Note { NoteId = 2, Title = "Micky", Message = "Maus" };
 
            // Act
            Repository.EditNote(noteToChange);
            Note changedNote = (from n in this.Context.Notes
                                where n.NoteId == noteToChange.NoteId
                                select n).First();
 
            // Assert
            Assert.That(changedNote.Title, Is.EquivalentTo(noteToChange.Title));
            Assert.That(changedNote.Message, Is.EquivalentTo(noteToChange.Message));
            Assert.That(this.Context.SavesChanged);
        }
 
        [TestMethod]
        public void DeleteNoteShouldThrowExceptionTest()
        {
            // Arrange
            const int UnknownId = 9999;
 
            // Act
            TestDelegate deleteAction = () => Repository.DeleteNote(UnknownId);
 
            // Assert
            Assert.DoesNotThrow(deleteAction);
        }
 
        [TestMethod]
        [Ignore]
        public void GetNoteShouldThrowExceptionTest()
        {
            // Arrange
            const int UnknownId = 9999;
 
            // Act
            TestDelegate getAction = () => Repository.GetNote(UnknownId);
 
            // Assert
            Assert.Throws<InvalidOperationException>(getAction);
        }
 
        [TestMethod]
        public void GetNoteShouldNotCallSaveChangesTest()
        {
            // Arrange
            var expected = new Note
                {
                    NoteId = 3,
                    Title = "Unit",
                    Message = "Test",
                    Added = DateTime.Parse("2010-10-29", CultureInfo.InvariantCulture)
                };
 
            // Act
            var actual = Repository.GetNote(expected.NoteId);
 
            // Assert
            Assert.That(actual, Is.EqualTo(expected));
            Assert.That(!this.Context.SavesChanged);
        }
 
        /// <summary>
        /// Returns a collection for the MockObjectSet
        /// </summary>
        /// <returns>three Notes</returns>
        public override List<Note> CreateNotesList()
        {
            DateTime friday = DateTime.Parse("2010-10-29", CultureInfo.InvariantCulture);
 
            return new List<Note>
                {
                    new Note { NoteId = 1, Title = "Hello", Message = "World", Added = friday },
                    new Note { NoteId = 2, Title = "Foo", Message = "Bar", Added = friday },
                    new Note { NoteId = 3, Title = "Unit", Message = "Test", Added = friday }
                };
        }
    }
}

Step 5: Download the sample solution

All shown files can reviewed in a demo solution!


Download the extension here: 
ADO.NET Unit Testable Repository Generator

Tags | , , , , , ,