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:
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:
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.