Highlights from my previous 199 ramblings – level 100 – 400

I started out reading blogs in early 2004 while in Iraq.  In March, I started
a blog at blogspot (and with a
little ‘customization’ of the stylesheet, I got it to redirect to my blog at
.Net junkies).  On April 16th, I transfered my initial posts to .Net junkies. 

One of the drawbacks of blogs is that old posts get buried even though the
information may continue to be relavent.  Here, I’ll review some topics:

I’m not sure how many regular readers I have (that isn’t my goal), but I
figured that on average, my blog website gets 430 hits per day.  Google is
responsible for most of them by matching up searches with content on my blog. 
Then another 500 RSS hits for most blog posts.

 

Looking back on my blog, it really is a journal of my coding experiences, and
I can see how far I’ve progressed. 

Local Agile lunch today – level 100

Today we had our second Agile lunch at the Mongolian BBQ.  We have a Yahoo
group at: http://groups.yahoo.com/group/BellwareNET to
coordinate locals interested in Agile methodologies.  We’ve decided to have our
meetings be over lunch since the attendance will be small; much smaller than the
Austin .Net User Group attendance.  At today’s meeting we discussed such topics
as:

– San Antonio user group web site

FitNesse
– Continuous integration, CruiseControl
– Testing user
interfaces
– NUnitForms
– Model-View-Presenter pattern
– DI, IOC,
Structure Map, Spring .NET

General application architecture diagram – level 300

Many applications I’ve encountered and most of my first applications had
loose or no defined architecture.   From a high level, everything just was.  And
it worked.  And it became hard to maintain.  I’ve been researching better ways
to organize the application and how to take advantage of high-level design
patterns.  With this knowledge, I’ve developed a general architecture for any
application with a UI (apps without a UI will just lack that layer, and, of
course, I haven’t included a service layer (which might even be the interface
layer).

My goal was to describe how the layers might interact and what bindings would
exist.  The most important things follow:  The UI layer holds references to the
process and business layers and no others.  The process layer holds references
to the repository, business, and UI layers.  The repository layer references
business and DAL.  The business layer references nothing (and this is key for
object portability).  The DAL references only the database (most likely through
the connection string) but holds no assembly references except ADO.NET, of
course.

With this architecture, we can implement Model-View-Presenter,  Repositories,
and Observer.   For example, the Process layer would hold presenter objects that
invoke business objects and set the View (UI).  The View observes business
objects but does not control them.  The Presenter objects control the process
layer and invoke the repository classes to get or persist the business objects. 
The repository layer does this by calling the correct classes of the DAL.  And
then, if the database changes (either in vender or schema), only the DAL needs
to be changed.  The DAL should expose classes that return data by calling the
right query in the database.  The DAL might wrap ADO.NET or perhaps the Data
Access Application Block for the direct database access.  The DAL would know the
names of stored procedures.  The repository objects would not know this.  Rather
the repository objects would just know what class and method to invoke to get
information with which to populate a business object.  The DAL should return
generic objects such as an IDataReader. 

I’ve read a lot about application design patterns and best practices, but I
wish there was some more architecture guidance out and about.  I think the
industry would benefit from standard approaches to application development from
a high level.  We hear a lot about n-tier and business layers, but a business
layer that knows how to persist its own objects is not the way to go, so I see
this guidance lacking.

Feedback is welcome on the above diagram.

Speaking schedule for the next quarter – level 000

On April 1st, I’ll be giving a talk on web services to a groups of students in a
.Net web development class at Texas A&M University.  Then on May 2nd, I’ll
be presenting to the Texas A&M .Net User Group an overview of the Dell IDD,
a smart client shell to host multiple applications.  Then I’ll move on to show
how to implement a plugin design in web applications.

Trying out the Model-View-Presenter pattern – level 300

After reading Martin
Fowler’s Model View Presenter article
, I did some deep thinking about how to
implement that pattern.  The purpose of the pattern is to decouple UI process
logic from the UI container.  If  you think about the code-behind classes in
your UI, all the examples we see have button-click handlers performing process
logic.  Below is my first attempt at creating a behavior layer for UI
testability and portability:

I’ll present this example using a simple ASP.NET page:

<%@ Page language=”c#” Codebehind=”default.aspx.cs”
AutoEventWireup=”false” Inherits=”ModelViewPresenter.WebForm1″
%>
<!DOCTYPE HTML PUBLIC “-//W3C//DTD HTML 4.0 Transitional//EN”
>
<HTML>
 <body>
  <form id=”Form1″ method=”post”
runat=”server”>
   <asp:textbox id=”txtName”
runat=”server”>
   </asp:textbox><asp:button id=”btnAdd”
runat=”server” Text=”Add Name”></asp:button>&nbsp;
   Number of
items:
   <asp:label id=”lblCount”
Runat=”server”></asp:label><br>
   <asp:datagrid
id=”dgdNames”
runat=”server”>
    <Columns>
     <asp:ButtonColumn
CommandName=”delete” ButtonType=”PushButton” Text=”Remove”
/>
    </Columns>
   </asp:datagrid></form>
 </body>
</HTML>

 

This page is used to maintain a list of names.  Type in a name and click the
add button; remove a name from the list.  The current names are shown in a
datagrid, and the count is shown next to the button.  Here is the
code-behind:

   14 public class WebForm1 : System.Web.UI.Page,
Presenter.INamesView
   15 {
   16     protected
System.Web.UI.WebControls.TextBox txtName;
   17     protected
System.Web.UI.WebControls.Button btnAdd;
   18     protected
System.Web.UI.WebControls.DataGrid dgdNames;
   19     protected
System.Web.UI.WebControls.Label lblCount;
   20 
   21    
private Presenter.NamesPresenter
_presenter;
   22 
   23     private
Model.Names _names {
   24         get { return
(Model.Names)ViewState[“names”]; }
   25    
    set { ViewState[“names”] = value; }
   26     }
   27 
   28    
private void
Page_Load(object sender, System.EventArgs
e)
   29     {
   30         _presenter = new Presenter.NamesPresenter(this);
   31    
    if(!IsPostBack) {
   32             _presenter.Load();
   33         }
   34     }
   35 
   36    
public Model.Names Names {
   37         get {
return _names; }
   38         set {
_names = value; }
   39     }
   40 
   41    
public void
Update() {
   42         dgdNames.DataSource
= _names;
   43        
dgdNames.DataBind();
   44 
   45         lblCount.Text =
_names.Count.ToString();
   46    
}
   47 
   48     private
void btnAdd_Click(object sender, System.EventArgs e) {
   49        
_presenter.AddName(txtName.Text);
   50    
    txtName.Text = string.Empty;
   51     }
   52 
   53    
private void
dgdNames_DeleteCommand(object source,
DataGridCommandEventArgs e) {
   54        
_presenter.RemoveName(e.Item.ItemIndex);
   55     }

 

I have omitted the using statements and the IDE-generated code, so this is
not complete, but it shows how I am delegating behavior to the presenter layer. 
Here is my presenter:

    5 public class NamesPresenter
    6 {
    7    
private INamesView _view;
    8 
    9    
public NamesPresenter(INamesView view)
{
   10         _view = view;
   11     }
   12 
   13    
public void
AddName(string nameToAdd) {
   14         _view.Names.Add(nameToAdd);
   15         _view.Update();
   16     }
   17 
   18    
public void
RemoveName(int indexOfNameToRemove) {
   19        
_view.Names.RemoveAt(indexOfNameToRemove);
   20         _view.Update();
   21     }
   22 
   23    
public void
Load() {
   24         _view.Names = new Model.Names();
   25         _view.Update();
   26     }
   27 }

 

This presenter controls the model (my business object) and tells the UI what
to do and when through the interface that the UI must implement (below):

    5 public interface INamesView
    6 {
    7    
Model.Names Names{get;set;}
    8    
void Update();
    9 }

 

As long as my UI implements this interface, my presenter can control it, and
I can make changes to the UI (including total replacement) without impacting the
core behavior. 

Next, all this exists to manage my model or business object:

    6 [Serializable]
    7 public class Names : IEnumerable
    8 {
    9    
private ArrayList _entries = new ArrayList();
   10 
   11    
public string
this[int
index] {
   12         get { return
_entries[index].ToString(); }
   13        
set { _entries[index] = value; }
   14     }
   15 
   16    
public int
Count {
   17         get { return
_entries.Count; }
   18     }
   19 
   20    
public void
Add(string name) {
   21         _entries.Add(name);
   22     }
   23 
   24    
public void
RemoveAt(int index) {
   25         _entries.RemoveAt(index);
   26     }
   27 
   28    
public IEnumerator GetEnumerator() {
   29         return
_entries.GetEnumerator();
   30    
}
   31 }

 

Events from the UI are delegated to the presenter, which decides what to do
and calls interface methods on the UI.  The presenter controls interaction
between the UI and the model just as a repository layer would control
presistence between the model and a data store.

 

I don’t pretend that this example is perfect, and I’m open for criticism, but
the model view presenter pattern for the UI is very tempting for testability and
UI portability.

Implementing a data repository class with a _true_ business object all with TDD – level 300

I’ve revised my previous sample that contained a Category class.  This
Category has an id, a name and description.  There is a Category table to
persist the object. I pulled everything data out of my business object and
created a CategoryData object that will know the DAL and know how to persist and
hydrate the Category object.  This approach greatly simplifies the business
object and decouples persisting the object to the database.  In the future, if I
changed the persistence method, I don’t have to change the business object, just
the data object.  Here are my sample classes:

Category:  note how simple my business object is now:

    7 public class Category {
    8 
    9    
private int
_id = 0;
   10     private string _name
= string.Empty;
   11     private
string _description = string.Empty;
   12 
   13    
public int ID
{
   14         get { return this._id; }
   15         set {
this._id = value; }
   16     }
   17 
   18    
public string
Name {
   19         get { return this._name; }
   20         set {
this._name = value; }
   21     }
   22 
   23    
public string
Description {
   24         get { return this._description; }
   25         set {
this._description = value; }
   26     }
   27 }

And my unit test class for this:

   12 [TestFixture]
   13 public class CategoryTest
   14 {
   15    
private Category _category = null;
   16 
   17    
public CategoryTest() {
   18         Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
   19     }
   20 
   21    
[SetUp]
   22     public void
GetACategory(){
   23         this._category = new
Category();
   24     }
   25 
   26    
[Test]
   27     public void
CreateCategory() {
   28        
Assert.IsNotNull(this._category);
   29     }
   30 
   31    
[Test]
   32     public void
CategoryID() {
   33         this._category.ID = 2;
   34         Assert.AreEqual(2, this._category.ID);
   35     }
   36 
   37    
[Test]
   38     public void
CategoryName() {
   39         this._category.Name = “Beverages”;
   40         Assert.AreEqual(“Beverages”,
_category.Name);
   41     }
   42 
   43    
[Test]
   44     public void
CategoryDescription() {
   45         this._category.Description =
“MyDescription”;
   46        
Assert.AreEqual(“MyDescription”, _category.Description);
   47     }
   48 }

Then I have my CategoryData object that knows how to persist using the
DAAB:

    7 public class CategoryData
    8 {
    9    
private Database _database = null;
   10 
   11    
public Database Database {
   12         get {

   13             if(this._database ==
null)
   14                 this._database =
DatabaseFactory.CreateDatabase(“DEV”);
   15             return this._database; }
   16         set {
this._database = value; }
   17     }
   18 
   19    
public Category GetCategory(int categoryID) {
   20         Category cat = null;
   21    
    using(IDataReader reader = this._database.ExecuteReader(“GetCategoryByID”,
categoryID)) {           
   22 
   23             if(reader.Read()){
   24                 cat = new Category();
   25                 cat.ID =
reader.GetInt32(reader.GetOrdinal(“CategoryID”));
   26                 cat.Name =
reader.GetString(reader.GetOrdinal(“CategoryName”));
   27                 cat.Description =
reader.GetString(reader.GetOrdinal(“Description”));
   28                 return cat;
   29             }else {
   30    
            return null;   
   31             }
   32         }
   33     }
   34 
   35    
public void
Insert(Category newCategory) {
   36        
newCategory.ID = (int)this._database.ExecuteScalar(“InsertCategory”,
newCategory.Name, newCategory.Description);
   37     }
   38 }

And the unit tests with stubs for the CategoryData class:

   12 [TestFixture]
   13 public class CategoryDataTest
   14 {
   15    
private CategoryData _categoryData = null;
   16 
   17    
[SetUp]
   18     public void
GetACategory(){
   19         this._categoryData = new CategoryData();
   20         this._categoryData.Database = new DatabaseStub();
   21     }
   22 
   23    
[Test]
   24     public void
GetCategory() {
   25         Category cat =
this._categoryData.GetCategory(1);
   26         Assert.IsNotNull(cat);
   27         Assert.AreEqual(1, cat.ID);
   28         Assert.AreEqual(“Beverages”,
cat.Name);
   29        
Assert.AreEqual(“MyDescription”, cat.Description);
   30     }
   31 
   32    
[Test]
   33     public void
GetCategoryThatDoesntExist() {
   34        
Category cat = this._categoryData.GetCategory(500);
   35         Assert.IsNull(cat);
   36     }
   37 
   38    
[Test]
   39     public void
InsertCategory() {
   40         Category
cat = new Category();
   41         cat.Name = “Jeffrey”;
   42         cat.Description = “Hello
category”;
   43         this._categoryData.Insert(cat);
   44         Assert.IsTrue(cat.ID == 400);
   45     }
   46 
   47    
internal class
DatabaseStub : SqlDatabase {
   48        
public override object
ExecuteScalar(string storedProcedureName, params object[]
parameterValues) {
   49             switch(storedProcedureName) {
   50                 case “InsertCategory”:
   51                     return 400;
   52                     break;
   53    
        }
   54 
   55             return null;
   56    
    }
   57 
   58 
   59    
    public override IDataReader ExecuteReader(string storedProcedureName, params object[]
parameterValues) {
   60 
   61             switch(storedProcedureName) {
   62                 case “GetCategoryByID”:
   63                     if(parameterValues.Length == 1 && (int)parameterValues[0] == 1) {
   64                         return new
DataReaderForCategory1Stub();
   65        
            }
   66                    
break;
   67             }
   68 
   69    
        return new EmptyDataReaderStub();
   70         }
   71     }
   72 
   73    
internal class
DataReaderForCategory1Stub : IDataReader  {
   74 
   75    
    public bool Read() {
   76             Trace.WriteLine(“Returning true
from Read()”, this.GetType().Name);
   77             return true;
   78    
    }
   79 
   80         public
string GetString(int index) {
   81             string retValue = string.Empty;
   82             switch(index) {
   83                 case 1:
   84    
                retValue = “Beverages”;
   85                     break;
   86    
            case 56:
   87                     retValue =
“MyDescription”;
   88                    
break;
   89             }
   90 
   91    
        return retValue;
   92         }
   93 
   94    
    public int
GetInt32(int index) {
   95             int retValue = int.MinValue;
   96             switch(index) {
   97                 case 0:
   98    
                retValue = 1;
   99        
            break;
  100             }
  101 
  102    
        return retValue;
  103         }
  104 
  105    
    public int
GetOrdinal(string name) {
  106             int retValue = 0;
  107             switch(name) {
  108                 case “CategoryName”:
  109                     retValue = 1;
  110                     break;
  111    
            case “CategoryID”:
  112                     retValue = 0;
  113                     break;
  114    
            case “Description”:
  115                     retValue = 56;
  116                     break;
  117    
        }
  118 
  119             return retValue;
  120         }
  121 
  122        
#region
IDataReader Members
  123 
  124         // extra members omitted
  279        
#endregion

  280     }
  281 
  282    
internal class
EmptyDataReaderStub : IDataReader {
  283        
#region
IDataReader Members
  284 
  285         // implementation omitted 
  468        
#endregion

  469 
  470     }
  471 }

This makes my model so much easier because now my business rules don’t have
to have anything to do with the database, and if we change databases later, my
business object doesn’t have to change.  I’ve been talking with Scott Bellware a lot lately
about Domain-driven design, and it’s some pretty deep stuff.  One thing we agree
on:  RAD sucks!

My first Test-Driven Development presentation – and concerns raised – level 100

Sorry folks, no code in this post. 

I just finished giving a one-hour presentation on how to do TDD with VS 2003
and NUnit.  I gave a brief overview of TDD but didn’t try to persuade them to
change right off the bat.  Heck, I’m just getting started!  I started with the
approach of referring them to the explanation given on AgileData.  Then I went into
a demonstration.  I emphasized the need to see the test fail to ensure that your
test is correct.  One time, I forgot to add an Assert to the test, and, of
course, it would never fail.  That hit home the point that seeing it fail
verifies that the test is good.

One of the concerns raised about using this methodology is:  “That’s a lot
more code to write”.  We talked as a group about the benefits of having unit
tests for all the code in a project.  The project could be shipped to another
building totally cut off from all networks, and another team could add
functionality and be sure they didn’t break anything else as long as all the
existing unit tests all continue to work.

Another question was if this approach would lead to better code. . .or “what
about the novice programmer”.  We talked about how this can lead to a clean
design but that it would not artificially make a bad programmer’s code better. 

I only started doing TDD last week, so if almost feels like I’m leading the
group while stumbling through the dark myself.  It’s becoming familiar quickly,
though.  I’m learning how to decouple external dependencies and test in
isolation, using SetUp and TearDown methods, etc.  Performance counters were a
bit tricky, though because I couldn’t decide if they should be considered an
external dependency that should be stubbed or not.  After all, I’m just calling
classes in the .Net Framework.  The code isn’t calling over the network.  With a
database, it’s clear:  stub it! 

Another topic that came up concerned some of our existing codebase.  We have
some class libraries that were designed to be consumed in a flexible manner, but
not test-first, and we don’t have unit tests for them.  Each of the classes has
about 5 overloaded constructors.  We discussed that if we developed it with TDD,
we’d only have the constructors that were required or that we tested.  We may
still decide that we want 5 constructors, but each one would have to have a
consuming test written first, and I would think all other tests on that class
would need to be performed with an object constructed with each of the
constructors.

The more I learn about TDD, the more I find I need to learn.  What a vicious
cycle!  I’m loving it, though.

TDD with the new Enterprise Library DAAB redux – level 300

Yesterday’s attempt at TDD with the DAAB prompted me to use NMock to imitate
the external dependency so my test would be a true _unit_ test.  Since then,
I’ve given it more thought – about the best way to proceed for future tests. 
I’ve revised my test and included two concrete stub classes:  one that derives
from the DAAB SqlDatabase class, and one that implements IDataReader.  These
classes have turned out to be easier to work with, and I like being able to see
the code directly in my test.  I would run against  a roadblock if I needed to
stub a class that didn’t implement an interface _and_ was sealed (I’m hoping
none of the .Net Framework is like this).

My Category class is the same:

    7 public class Category {
    8 
    9    
private string
_name = string.Empty;
   10     private
static Database _database = null;
   11    
private static
string _databaseInstance = “DEV”;
   12 
   13    
public string
Name {
   14         get { return this._name; }
   15         set {
this._name = value; }
   16     }
   17 
   18    
public static
Database Database {
   19         get {
   20    
        if(_database == null)
   21    
            _database =
DatabaseFactory.CreateDatabase(_databaseInstance);
   22 
   23    
        return _database;
   24         }
   25         set {
_database = value; }
   26     }
   27 
   28    
public Category(int categoryID)
   29     {
   30         IDataReader reader =
Category.Database.ExecuteReader(“GetCategoryByID”, categoryID);
   31 
   32    
    if(reader.Read()){
   33             this._name =
reader.GetString(reader.GetOrdinal(“CategoryName”));
   34         }
   35     }
   36 }

 

But my unit test class has changed.  The [Test] method has been simplified
with the use of concrete stubs instead of dynamic Mocks.  My stubs are nested
classes so that they are truly dedicated to this test class:

   12 [TestFixture]
   13 public class CategoryTest
   14 {
   15    
public CategoryTest() {
   16         Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));
   17     }
   18 
   19    
[Test]
   20     public void
GetACategory(){
   21        
Category.Database = new
DatabaseToReturnCategory1();
   22 
   23         Category existing = new Category(1);
   24         Assert.AreEqual(“Beverages”,
existing.Name);
   25     }
   26 
   27    
public class
DatabaseToReturnCategory1 : SqlDatabase {
   28         public
override IDataReader ExecuteReader(string storedProcedureName, params object[]
parameterValues) {
   29             return new
DataReaderToReturnBeveragesAsCategoryName();
   30         }
   31     }
   32 
   33    
public class
DataReaderToReturnBeveragesAsCategoryName : IDataReader  {
   34         public
bool Read() {
   35             Trace.WriteLine(“Returning true
from Read()”, this.GetType().Name);
   36             return true;
   37    
    }
   38 
   39         public
string GetString(int index) {
   40             string retValue = string.Empty;
   41             switch(index) {
   42                 case 1:
   43    
           
    Trace.WriteLine(“Returning Beverages from
GetString(int)”, this.GetType().Name);
   44                     retValue =
“Beverages”;
   45                     break;
   46    
        }
   47 
   48             return retValue;
   49         }
   50 
   51    
    public int
GetOrdinal(string name) {
   52             int retValue = 0;
   53             switch(name) {
   54                 case “CategoryName”:
   55                     Trace.WriteLine(“Returning
1 from GetOrdinal(string)”, this.GetType().Name);
   56                     retValue = 1;
   57                     break;
   58    
        }
   59 
   60             return retValue;
   61         }
   62 
   63        
#region
IDataReader Members
   64 
— unneeded stub methods not
posted
  224 
  225        
#endregion

  226     }
  227 }

 

I have started a switch statement in the stubs so that I can easily add some
more cases to test the other fields that I expect back.

Note also my use of a trace listener.  I’ve grown to prefer Trace.Writeline
instead of Console.Writeline because with Trace I can hook up more listeners and
also get this output to other callers.  Using Console.Out with the listeners
also allows me to get these statements to the console (and the NUnit gui).

This approach is more straight-forward to me than dynamic mocks, so I’m going
to stick with this approach as much as I can.

This afternoon I’ll be giving a presentation to my team about TDD and doing
this demo to help get them started.  I hoping my team can quickly start using
iterative development to drive quality and flexibility in our software.

TDD with the new Enterprise Library DAAB – level 300

First, I give props to they guys at Microsoft who put out the Enterprise
Library.  I especially like the data access application block.  I do, however,
have one beef with it.  Everyone preaches “code to an interface”, and ADO.NET
exhibits this (IDataReader, IDbCommand, etc), but the DAAB doesn’t do this. 
Consequently, I can’t stub out a mock object to decouple the DAAB from the code
I’m trying to unit test with NUnit.  I then tried NMock to create a dynamic
mock, but the ExecuteReader(string, params object) method wasn’t marked as
virtual.  After changing it to virtual and recompiling the source, NMock would
work (it appears most methods were marked virtual, but that some were
overlooked).  Not having the interface to stub out _really_ makes TDD
difficult.  It forces me to use dynamic mocks (which are more brittle).

Here’s a quick test I whipped up to create a Category class that is a record
in the Categories table of Northwind.  Note the use of NMock to get my unit test
to work without the dependency on the DAAB:

    7 public class Category {
    8 
    9    
private string
_name = string.Empty;
   10     private
static Database _database = null;
   11    
private static
string _databaseInstance = “DEV”;
   12 
   13    
public string
Name {
   14         get { return this._name; }
   15         set {
this._name = value; }
   16     }
   17 
   18    
public static
Database Database {
   19         get {
   20    
        if(_database == null)
   21    
            _database =
DatabaseFactory.CreateDatabase(_databaseInstance);
   22 
   23    
        return _database;
   24         }
   25         set {
_database = value; }
   26     }
   27 
   28    
public Category(int categoryID)
   29     {
   30         IDataReader reader =
Category.Database.ExecuteReader(“GetCategoryByID”, categoryID);
   31 
   32    
    if(reader.Read()){
   33             this._name =
reader.GetString(reader.GetOrdinal(“CategoryName”));
   34         }
   35     }
   36 }

Now my test:

   10 [TestFixture]
   11 public class CategoryTest
   12 {
   13    
[Test]
   14     public void
GetACategory(){
   15 
   16         Mock mockDatabase = new NMock.DynamicMock(typeof(Database));
   17         Mock mockReader = new NMock.DynamicMock(typeof(IDataReader));
   18 
   19    
    mockReader.ExpectAndReturn(“GetString”, “Beverages”, 56);
   20        
mockReader.ExpectAndReturn(“GetOrdinal”, 56, “CategoryName”);
   21         mockReader.ExpectAndReturn(“Read”,
true);
   22        
mockDatabase.ExpectAndReturn(“ExecuteReader”, mockReader.MockInstance,
“GetCategoryByID”, new object[]{1});
   23 
   24    
    Category.Database = (Database)mockDatabase.MockInstance;
   25 
   26    
    Category existing = new
Category(1);
   27        
Assert.AreEqual(“Beverages”, existing.Name);
   28 
   29    
    mockReader.Verify();
   30        
mockDatabase.Verify();
   31     }
   32 }

I had to use NMock for the Database class, so I just used it for the
IDataReader interface as well (as I further this class, I will modify that to
use a mock stub that implements IDataReader).

This code work and allows me to test the instantiation of my Category object
with the ID of a category.

The data access block is awesome, but I WISH I had an interface to code
against instead of just the abstract class.  I guess I’m going to have to insert
the interface myself.

By the way, I attended the webcast about this block this afternoon, and I
have to say that it was the most fun webcast I’ve every attended.  The
presenters were in shorts and cutting up and laughing the whole time.  🙂