Subscribe in a reader
Nermin's .Net - All posts by Admin
Nermin's .Net
My Thoughts on .Net and Software Development

Mock ADO.NET with ease using IDataReader Stub objects

July 10, 2007 11:16 by Admin

Before I start, I would like to point out that if you are confused about differences between Mock and Stub objects, please read the Fowler’s post on the subject:

http://www.martinfowler.com/articles/mocksArentStubs.html

I have seen too many “Unit tests” where developers do not isolate the test to the unit (object/method) being tested.  Yes they are testing a business object, but to test its behavior they load half of the object hierarchy in the project.  Moreover if your object gets initialized from external resource like a database, then they create this complex “test databases” that contain their test data.  These databases have to be shared with other developers.  If you have a continuous build environment that runs tests as a part of the build process, then you have to have a copy of the test database there.  All these test databases have to be modified as you modify schema/data in your development database.  In addition if your test modifies data in the database then you need to setup an additional process in the SetUp or Teardown to restore the data to initial state.

So the test should be simpler if we mock the db dependency, right?  So what does that involve?  Let’s say we have an object called project Project with constructor as described below:

public Project(IProjectGateway gateway, int id)

{

    using(IDataReader dr = gateway.GetProjectBy(id)) {

        if(dr.Read()) {

            _id = dr.GetInt32(0);

            _name = dr.GetString(1);

            _date = dr.GetDateTime(2);                   

        }

    }

}

 

Where IProjectGateway is an interface defining a set of methods/and object in charge of persistence of the Project data to and from the database.    So lets look how that interface might look like:

public interface IProjectGateway {

    IDataReader GetProjectBy(int id);

    ...

}

So far this is simple, right? Actual implementation of that interface does not matter for our test.  Why?  Because we are not testing database, its resources/file storage, hardware, connection pooling, network connections, etc.  All we are supposed to test is that our object properly populates its field from a returned DataReader.  

To test the Project object without the database roundtrip we will only need to mock the IProjectGateway, setting the expectations for the GetProjectBy(id) to return our test data (data reader).  I have to mention that the dynamic mocks in the examples bellow were done using my favorite mocking tool TypeMock.Net.

[Test]

public void AssureFetchMapsFields()

{

    Mock<IProjectGateway> projGatewayMock = MockManager.Mock<IProjectGateway>();

 

    projGatewayMock.ExpectAndReturn("GetProjectBy", new ProjectDataStub().CreateDataReader());

   

    Project project = new Project(projGatewayMock.MockedInstance,1);

 

    Assert.AreEqual(1,project.Id);

    Assert.AreEqual("Test",project.Name);

    Assert.AreEqual(DateTime.Parse("1/1/2000"),project.Date);

}

 

So lets see what exactly have we done in the test above.  First line creates our dynamic mock instance.  Second line is the interesting part.  It states that we expect one method call on our IProjectGatewayMock, and that is “GetProjectBy()” method.  Once it is called we want the IDataReader to be returned from ProjectDataStub.CreateDataReader().  The rest of the code instantiates the Project object and then assures that the Project’s properties are initialized.

But what about this ProjectDataStub.CreateDataReader()?  Well I have noticed the ability of the DataTable objects to create an instance of TableDataReader(which implements IDataReader).  So theoretically we could create a DataTable with column types that reflect the types of the actual columns of the table/view we are fetching from db and populate this DataTable with test record(s).  Then our mock IProjectGateway can return the IDataReader from this object, and voila – no db or any other external connection used in the test.

So if we follow this logic the ProjectDataStub should be an object that inherits from DataTable and populates its columns and rows with test records when it is constructed.  But coding these stub object for each and every test might be a bit tedious.  To solve this problem I have created a rather simple tool that allows us to generate this DataStub simply by copying and pasting select SQL statements from the fetch Stored Procedure and executing it.

Above is the scren shot showing how tool works and its output.  If you think that this tool might be useful for you feel free to download the code from the link bellow:

StubGenerator.zip (780.62 KB)

Is this all when it comes to testing the DAL?  No, obviously we have only tested the data mapping part.  Code in this Project constructor can throw SqlExcpetion (database down, network problem, schema problem).  We need to assure that our code handles that.

Now putting the try/ctach block in the Project constructor does not make sense - I do not want Project instantiated if we were unable to retreive its data.  So how do we test this case?  Lets assume that our application is using Model View Presenter architecture, and that the object instantiating our Project is the Presenter object of the View that displays Project.  Obviously we need to assure that this Presenter can recover from the SqlException thrown by Project.  Lets take a look at the code bellow:

public class ProjectPresenter

{

....

public void DisplayProject(){

    try{

        Project p = new Project();

 

        ... do something with project like display it on the view etc...

 

    }catch(SqlException e){

        Log.LoqException(e);       

    }

}

So if we can assure that the Log.LogException(e) is called when the Project throws the SqlException, that would be a proof that the exception was handled.  Keep in mind that in Test Driven Development we would be writting the test prior to the DisplayProject() method being written (and the catch block inside of it existing)

Dynamic mocking helps us here also.  In this case we are testing the Presenter, which means that the other two objects Log and Project would be mocked.  Test would encompass mocking ProjectConstructor instead of returning Project throws SqlException, and then assuring that the Log Mock accepts the call to LogException(e).

In addition there would be tests that we need to run for Insert, Update and Delete (if Project needs to support that), but I will leave that for a future post.


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: C# | Mock | TDD | Unit Testing
Actions: E-mail | Permalink | Comments (3) | Comment RSSRSS comment feed

Silverlight to support Ruby, Python

May 1, 2007 14:19 by Admin

It looks like Microsoft has just raised stakes in its "war on Flash".  Silverlight, formely known as WPFe is to provide a Dynamic Language Runtime, which will provide  a shared set of language services such as a dynamic type system, fast dynamic dispatch, smart code generation, and a hosting API.  Languages to support this platform include JavaScript, C#, VB, Ruby, Python, and more.

Check out this post by Somasegar's blog:

http://blogs.msdn.com/somasegar/archive/2007/04/30/mix-07-silverlight-shines-brighter.aspx


Be the first to rate this post

  • Currently 0/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: Silverlight | WPFe
Actions: E-mail | Permalink | Comments (0) | Comment RSSRSS comment feed

TDD/Using Mock objects with CSLA.Net

April 30, 2007 17:29 by Admin

I must admit that I am a huge fan of Test Driven development.  Although I generally use CRC process to design my classes and their interactions, I tend to use TDD process to fine-tune the collaborations between these objects, and generally simplify my initial object design.  While I know that there are many skeptics in usefulness of TDD as a software design process, I believe that they underestimate one important factor in developer’s arsenal: laziness!  After a while each one of us tries to find a way to minimize the number of tests they have to write per object you implement.  If you build it in its simplest form, minimizing interactions and state permutations you minimize the number of the tests.  In addition tests help us understand how objects is used/how it behaves/interacts with other objects.  And most importantly test that we write give us that safety net to facilitate change, refactor code without constant worry that we might break existing functionality.  

Mocks on the other hand are the mechanism that assures that tests focus on the unit/component being tested and not the components that this unit interacts with.  When the tested code uses other components things can get quite fragile and the tests will quickly become system tests.  Examples are classes that use a database, a logging system, web service and any other external components.  These external components might require a complex setup. For example, in order to run a test that uses a database, we must have a running database with the tables and data setup correctly for the test (we must cleanup this data before each test runs).  Too much work for a lazy developer, and more importantly test results easily compromised by factors that are out of our control.

So mocking in this case sounds like a valid solution.  But what is the problem in implementing this in a CSLA world?  Well, CSLA has this concept of ‘Mobile Objects’, which means that the object is generally created in the (App) Server context, and then serialized to the client.  For example let’s take a look at the way we retrieve ProjectList object from the sample ProjectTracker20cs project.

/// <summary>Return a list of all projects.</summary>

public static ProjectList GetProjectList()

{

return DataPortal.Fetch<ProjectList>(new Criteria());

}

or,

/// <summary>Return a list of projects filtered by project name.</summary>

public static ProjectList GetProjectList(string name)

{

    return DataPortal.Fetch<ProjectList>

      (new FilteredCriteria(name));

}

For all of us that use CSLA daily this means that the DataPortal is going to instantiate the object of type ProjectList, call appropriate override of the method DataPortal_Fetch() defined in the ProjectList, and finally serialize it back to the client where that instance is returned trough the factory method in question. 

DataPortal_Fetch method overrides should resemble something like this:

private void DataPortal_Fetch(Criteria criteria)

{

    // fetch with no filter

    Fetch("");

}

private void DataPortal_Fetch(FilteredCriteria criteria)

{

    Fetch(criteria.Name);

}

private void Fetch(string nameFilter)

{

    RaiseListChangedEvents = false;

    using (SqlConnection cn = new SqlConnection(Database.PTrackerConnection)) {

        cn.Open();

        using (SqlCommand cm = cn.CreateCommand()) {

            cm.CommandType = CommandType.StoredProcedure;

            cm.CommandText = "getProjects";

            using (SafeDataReader dr = new SafeDataReader(cm.ExecuteReader())) {

                IsReadOnly = false;

                while (dr.Read()) {

                    ProjectInfo info = new ProjectInfo(

                      dr.GetGuid(0),

                      dr.GetString(1));

                    // apply filter if necessary

                    if ((nameFilter.Length == 0) || (info.Name.IndexOf(nameFilter) == 0))

                        Add(info);

                }

                IsReadOnly = true;

            }

        }

    }

    RaiseListChangedEvents = true;

}

Now let’s take a look at how most of the mocking frameworks mock dependencies.  Generally one needs to create an interface on the object we are mocking, and then pass the reference to that interface to the object we are trying to test.  This is essentially the implementation of the “Dependency injection pattern”, where the actual implementation is passed as this interface at run time, or mock object during the tests.  This, as far as I can tell, applies to NMock, EasyMock, or RhinoMock.

So the problem is that these mocking tools require us to build “mockable” objects.   This will not work with CSLA, or at least will not be implemented easily.  The problem is that, if one wants to mock dependencies such as data access layer components (db connection, data reader, command) one would have to instantiate them on the client side and then “inject” them as arguments into the Factory Method being called, making sure that they are somehow serialized to the server side.  And naturally database components are not serializable.

So, is it possible to mock CSLA dependencies that reside only on server side and are not serialized back and forth?  The answer is “Yes”.  Yes if you use TypeMock.Net library.  What is the major advantage of this tool when compared to other .Net mocking tools?  TypeMock uses Aspect Oriented technology to redirect calls from the real code to the mock object instantiated.  So how does this work?

Before we try to mock dependencies we have to remember one of the golden rules of Mocking:  “Never to Mock classes/interfaces you do not own or have source code to”.  What does that mean?   I have seen code where developers tried to Mock interfaces as IDataReader (or SqlDataReader) for example.  That interface is too complex and it is not something I defined or have control over.  So the first thing I would like to do is build a class called Database, that encapsulates all of the database communication in the Fetch() method.  So let’s do a little refactoring:

private void Fetch(string nameFilter)

{

    RaiseListChangedEvents = false;

    using (Database db = new Database(Database.PTrackerConnection)) {

        SqlCommand cm = db.CreateSPCommand("getProjects");

        using (SafeDataReader dr = db.ExecuteSafeDataReader(cm)) {

            IsReadOnly = false;

            while (dr.Read()) {

                ProjectInfo info = new ProjectInfo(

                  dr.GetGuid(0),

                  dr.GetString(1));

                // apply filter if necessary

                if ((nameFilter.Length == 0) || (info.Name.IndexOf(nameFilter) == 0))

                    Add(info);

            }

            IsReadOnly = true;

        }

    }

    RaiseListChangedEvents = true;

}

Let us compare the code above to the original Fetch().  One can notice that instead of creating SqlConnection object we created a Database object passing its constructor a desired connection string.  You will also notice that we are not explicitly “Opening” database connection.  That is because the Database class is managing SqlConnection internally and opening it as needed (for example, within the Database.ExecuteSafeDataReader() call as you might notice bellow when we take a look at the Database class).   

In addition you will notice that we have removed the using block around the SqlCommand instance.  Again the Database instance manages SqlCommand objects it creates and disposes them at the time it is disposed itself (together with disposing a SqlConnection).

 Below is a simplified version of the Database class.  Some of you might notice s similarity to the Database class implemented in Enterprise Library.  I do generally use Enterprise Library, and the pattern used in their Data Access Block makes it easier to test/mock DAL objects.

public class Database : IDisposable

{

    private readonly SqlConnection _activeConnection;

    private readonly List<SqlCommand> _createdCmds;

    private bool disposed;

    public Database(string connection)

    {

        _activeConnection = new SqlConnection(connection);

        _createdCmds = new List<SqlCommand>();

    }

    ~Database()

    {

        Dispose(false);

    }

    #region Available Connection Strings

    public static string PTrackerConnection

    {

        get

        {

            return ConfigurationManager.ConnectionStrings

                ["PTracker"].ConnectionString;

        }

    }

    public static string SecurityConnection

    {

        get { return ConfigurationManager.ConnectionStrings["Security"].ConnectionString; }

    }

    #endregion

    #region IDisposable Members

    public void Dispose()

    {

        Dispose(true);

        GC.SuppressFinalize(this);

    }

    protected virtual void Dispose(bool disposing)

    {

        if (!disposed) {

            if (disposing) {

                // Dispose managed resources.

                foreach (SqlCommand cmd in _createdCmds)

                    cmd.Dispose();

                _createdCmds.Clear();

                if (_activeConnection != null && _activeConnection.State != ConnectionState.Closed)

                    _activeConnection.Close();

            }

            // Dispose unmanaged resources

        }

        disposed = true;           

    }

    #endregion

    protected  void OpenConnection()

    {

        if (_activeConnection.State!=ConnectionState.Open)

            _activeConnection.Open();

    }

    public SqlCommand CreateSPCommand(string cmdName)

    {

        SqlCommand cm = _activeConnection.CreateCommand();

        cm.CommandType = CommandType.StoredProcedure;

        cm.CommandText = cmdName;

        _createdCmds.Add(cm);

        return cm;

    }

    public SafeDataReader ExecuteSafeDataReader(SqlCommand cm)

    {

        OpenConnection();

        return new SafeDataReader(cm.ExecuteReader());

    }

    public void AddWithValue(SqlCommand cm, string paramName, object value)

    {

        cm.Parameters.AddWithValue(paramName, value);

    }

}

NUnit uses Test Fixture concept to group tests applied to a single unit of code.  So since we are going to test the ProjectList object let’s create that Test Fixture:

[TestFixture]

public class ProjectListTest

{

    [SetUp]

    public void Start()

    {

        ///<remark>Initialize TypeMock before each test</remark>

        MockManager.Init();

    }

   

    [TearDown]

    public void Finish()

    {

        ///<remark>We will verify that the mocks have been called correctly at the end of each test</remark>

        MockManager.Verify();

    }

}

As you can see in order to use TypeMock in our tests we need to Initialize the TypeMock’s MockManager first and then call Verify() at after the test has run.

Now we are ready to write our first test.  Generally my first test is something extremely simple like making sure that the operation returned a result.  So the first test is going to be the one that ensures that the ProjectList.GetProjectList() creates and adds a single ProjectInfo object.

[Test]

public void LoadsOne()

{

    ProjectList item = ProjectList.GetProjectList();

    Assert.AreEqual(1,item.Count);

}

This first test does not have any mocks obviously, and if we run it we are going to see the following error:

ProjectTracker.Library.Tests.ProjectListTest.LoadsOne : Csla.DataPortalException : DataPortal.Fetch failed (System.NullReferenceException: Object reference not set to an instance of an object.

   at ProjectTracker.Library.Database.get_PTrackerConnection() in C:\Development\csla20cs\ProjectTracker20cs\ProjectTracker.Library\Database.cs:line 37

   at ProjectTracker.Library.ProjectList.Fetch(String nameFilter) in C:\Development\csla20cs\ProjectTracker20cs\ProjectTracker.Library\ProjectList.cs:line 73

   at ProjectTracker.Library.ProjectList.DataPortal_Fetch(Criteria criteria) in C:\Development\csla20cs\ProjectTracker20cs\ProjectTracker.Library\ProjectList.cs:line 62)

  ----> Csla.Server.CallMethodException : DataPortal_Fetch method call failed

  ----> System.NullReferenceException : Object reference not set to an instance of an object.

The error above states that the line where we tried to call new Database(Database.PTTrackerConnection) failed due to static property PTTrackerConnection trying to access external configuration file to read a connection string.  So we will need to mock that call.  In addition we will need to mock the whole Database instance, since the Database object internally instantiates the SqlConnection (another external resource not available to us for this unit test).  So let us write the code that does that.

 [Test]

public void LoadsOne()

{

    Mock mockDb = MockManager.Mock(typeof(Database));

    mockDb.ExpectGet("PTrackerConnection", string.Empty);

    mockDb.ExpectAndReturn("CreateSPCommand", null);

    mockDb.ExpectAndReturn("ExecuteSafeDataReader", new SafeDataReader(GetDataReaderStub()))

         .Args(null);

    mockDb.ExpectCall("Dispose");

    ProjectList item = ProjectList.GetProjectList();

    Assert.AreEqual(1,item.Count);

}

private IDataReader GetDataReaderStub()

{

    return new DataTable().CreateDataReader();

}

We have added few lines to our test.  The first line allows defines the object that we are going to mock.  Following four lines define the behaviors of the Database objects that we are going to intercept and replace with our values that we need for the test, therefore taking the database out of equation.  As we can see from line:

mockDb.ExpectGet("PTrackerConnection", string.Empty);

We are expecting a Property Get call on the property called PTrackerConection and we want it to return a constant string.Empty.  Then we are expecting a method call to “CreateSPCommand” to be called, and want our mock Database to return null (we do not care about the SqlCommand since the mock Database object is not going to be using it anyway).  Following line is where it gets interesting:

    mockDb.ExpectAndReturn("ExecuteSafeDataReader", new SafeDataReader(GetDataReaderStub()))

         .Args(null);

As you can see we expect that the call to ExecuteSafeDataReader returns Data Reader as defined in the GetDataReaderStub() method.  If we run the test now following will be the output:


NUnit.Framework.AssertionException:   Expected: 1

  But was:  0


at NUnit.Framework.Assert.That(Object actual, IConstraint constraint, String message, Object[] args)
at NUnit.Framework.Assert.AreEqual(Int32 expected, Int32 actual, String message, Object[] args)
at NUnit.Framework.Assert.AreEqual(Int32 expected, Int32 actual)
at ProjectTracker.Library.Tests.ProjectListTest.LoadsOne() in ProjectListTest.cs:line 42

Since the GetDataReaderStub() method is supposed to return a IDataReader that is constructed from the empty DataTable, then the number of items in the ProjectList should be zero.  More importantly we have successfully mocked the data access layer code although our test is still failing (we want to ensure that our test inserts one item from mock Database into the ProjectList).  Proof of successful mock is the fact that we are not getting any ado.net exceptions when we run the test – meaning that all of the calls to the Database object are intercepted as we expected.  Assuring that test is successful will require us to modify the GetDataReaderStub() method to create a DataTable with the signature that is expected in fetch method, and with the number of the records that are expected in the result (1). 

But before we do that let’s first clean the test code.  I generally do not want to crowd the code in the actual test with bunch of the details of the internal mocks.  In  addition it seems that there will be a common pattern in the way we fetch records, so I believe we can extract the Mock calls to a helper method called MockDatabaseFetchCall().  Also if this is to be method that is shared between multiple Test Fixtures we should move it outside of this Test Fixture.  Let’s see how our code looks like after that refactoring.

internal class MockHelper

{

    public static void MockDatabaseFetchCall(string connectionName, int noOfAddInParamCalls, IDataReaderStubFactory drFactory)

    {

        Mock mockDb = MockManager.Mock(typeof(Database));

        mockDb.ExpectGet(connectionName, string.Empty);

        mockDb.ExpectAndReturn("CreateSPCommand", null);

        mockDb.ExpectCall("AddWithValue", noOfAddInParamCalls);

        mockDb.ExpectAndReturn("ExecuteSafeDataReader", drFactory.GetDataReaderStub())

            .Args(null);

        mockDb.ExpectCall("Dispose");

    }       

}

We can see that the MockDatabaseFetchCall() method has 3 parameters.  The necessity for the first parameter is due to the fact that our Database object has two “connection string” properties: “PTrackerConnection” and “SecurityConnection”.  Argument connectionName, allows us to specify which of the two we will mock.  We can see that the second parameter is related to the new line in our method:

mockDb.ExpectCall("AddWithValue", noOfAddInParamCalls);

What does that line mean? The line states that we expect a call to the method called AddWithValue() noOfAddInParamCalls times, and that we are going to ignore parameters or the return value.  We just want to ensure that the calls are made.  But the method AddWithValue did not exist in our original definition of the Database class.  We have added this method as a part of this last refactoring. Here is what it does:

public void AddWithValue(SqlCommand cm, string paramName, object value)

{

cm.Parameters.AddWithValue(paramName, value);

}

In some of the Fetch() methods we want to pass parameters to the stored procedure that allow us to filter the data within stored procedure.  Then our Fetch call signature changes.  For each parameter there is an extra call to the AddWithValue() method.   

Now let’s move onto the third parameter:  IDataReaderStubFactory drFactory.  It is an interface that defines a single method:

internal interface IDataReaderStubFactory

{

    SafeDataReader GetDataReaderStub();

}

Basically since MockHelper.MockDatabaseFetchCall() is a shared method, and every list object’s (BusinessListBase<T>, or ReadOnlyBase<T>) Test Fixture will have one or more IDataReader Stubs, I decided to implement them as an interface.  Here is the implementation for our “one record fetch” of the ProjectList:

public class ProjectListFetchOneDRStub : IDataReaderStubFactory {

    public SafeDataReader GetDataReaderStub()

    {

        DataTable stubTable = new DataTable();

        stubTable.Columns.Add("pk",typeof(Guid));

        stubTable.Columns.Add("desc", typeof (string));

        stubTable.Rows.Add(new object[]{Guid.NewGuid(),string.Empty});

        return new SafeDataReader(stubTable.CreateDataReader());

    }

}

As you can see we are actually generating a DataTable with columns that match structure expected in ProjectList.Fetch() method.  In addition we are generating a single row of data.

Taking all this into account our modified test code should look like this:

[Test]

public void LoadsOne()

{

    MockHelper.MockDatabaseFetchCall("PTrackerConnection", 0, new ProjectListFetchOneDRStub());

    ProjectList item = ProjectList.GetProjectList();

    Assert.AreEqual(1,item.Count);

}

After running this test we can see that the test passes.  Project list successfully fetches and inserts one item.  Now this looks like a lot of work for our first test, but note how easy it is to create future tests of this type.  Let’s say we want to test the other path in creation of the Project List – ProjectList.GetProjectList(string name).

[Test(Description = "DataReader returns 3 items but only one should be inserted, based on filter")]

public void LoadsThreeFiltersTwo()

{

    MockHelper.MockDatabaseFetchCall("PTrackerConnection", 0, new ProjectListFetchThreeDRStub());

    ProjectList item = ProjectList.GetProjectList("test");

    Assert.AreEqual(1, item.Count);

}

The main difference between this one and our first test, besides us calling the GetProjectList(“test”) with the string argument is that we pass a different IDataReaderStubFactory implementation – ProjectListFetchThreeDRStub.  And that class is defined as:

public class ProjectListFetchThreeDRStub : ProjectListFetchBaseDRStub {

    public override SafeDataReader GetDataReaderStub()

    {

        DataTable stubTable = GetStubTable();

        stubTable.Rows.Add(new object[] { Guid.NewGuid(), "test is important" });

        stubTable.Rows.Add(new object[] { Guid.NewGuid(), "" });

        stubTable.Rows.Add(new object[] { Guid.NewGuid(), "this test record will not be included" });

        return new SafeDataReader(stubTable.CreateDataReader());

    }

}

You will notice that I have followed my usual behavior and have refactored ProjectListFetchThreeDRStub (when compared to original ProjectListFetchOneDRStub).  I have extracted the code that instantiates a DataTable, and creates column structure into a method called GetStubTable().  This method was moved into a base abstract class called ProjectListFetchBaseDRStub, and both ProjectListFetchThreeDRStub, and ProjectListFetchOneDRStub now inherit from it.  Here is the code of the base class:

public abstract class ProjectListFetchBaseDRStub : IDataReaderStubFactory {

    public abstract SafeDataReader GetDataReaderStub();

    protected static DataTable GetStubTable()

    {

        DataTable stubTable = new DataTable();

        stubTable.Columns.Add("pk", typeof(Guid));

        stubTable.Columns.Add("desc", typeof(string));

        return stubTable;

    }

}

Second test also passes.  Although the we have a SafeDataReader with 3 rows only the first one has a Name that begins with “test”. 

We can use the same IDataReader Stub to construct the ProjectInfo tests, like:

[TestFixture]

public class ProjectInfoTest

{

    [Test]

    public void AssureFieldsMapped()

    {

        SafeDataReader dr = (new ProjectListFetchOneDRStub()).GetDataReaderStub();

        dr.Read();

        ProjectInfo info = new ProjectInfo(

            dr.GetGuid(0),

            dr.GetString(1));

        

        Assert.IsNotNull(info);

        Assert.AreEqual(string.Empty,info.Name);

    }

}

Again this is a rather simple test just to show you one of the possible patterns to use in BusinessBase<T> or ReadOnlyBase<T> tests.  Once you have your object constructed from the Data Stub you can run tests that involve business logic, state and behavior of the object.

One might notice that there was a possibility of mocking a DataPortal itself within ProjectList.GetProjectList() method.  Two important issues with that path are that first we would not be testing the code running within the Fetch() method, and the necessity to change an accessibility of constructor of the ProjectList class from private to public (to have Mock DataPortal return an instance). 

In future posts I will explore mocking of the portions of the code that perform DB insert/update/delete, as well as more efficient way of generating IDataReader Stubs.

 

>>

Currently rated 5.0 by 1 people

  • Currently 5/5 Stars.
  • 1
  • 2
  • 3
  • 4
  • 5
Tags:
Categories: C# | Csla.Net | Mock | TDD | Unit Testing
Actions: E-mail | Permalink | Comments (2) | Comment RSSRSS comment feed