Welcome to

Magenic Technologies Community Blog

Sign in | Join | Help

Nermin Dibek

All about .Net
RhinoMocks 3.5 AAA Model
Ayende has again proven why he is one of the most respected names in Alt.Net community.  Besides writing a book on language based DSLs, supporting Boo, and NHibernate, having a full time job, and writing one of the most informative blog publications, he has actually practically re-written RhinoMocks in this new version.  And with that RhinoMocks basically takes back the title of simplest and most productive dynamic mocking framework out there.

Take a look at an ASP.NET MVC test written with RhinoMocks 3.3:

Test with RhinoMocks 3.3 

As you can see the test above uses a traditional Record & Replay model (referred to as R&P in the rest of this document), where in Record block we generally set our expectations, and then the Replay block is used to perform actions on object being tested,  allowing our Mock objects to execute and verify expectations.

Now let’s take a look at the same test written with RhinoMocks 3.5:

 Test with RhinoMocks 3.5

This test uses Arrange, Action and Assert model (AAA).  What you will notice first is that there are by far fewer lines needed to setup mocks.

In the AAA version there is no need to instantiate MockRepository, once you generate your Mock, or in this case Stub object, you can setup your expectations directly on the mock instance. Lines 21 and 22 in R&P version of the test are replaced by single line of code in AAA version – line 22.

You will also notice that we are using GenerateStub() instead of DynamicMock().  Put simply there is a difference between Mock and Stub objects and RhinoMocks recognizes that allowing us to write tests that better state their purpose.  For some of you scratching your heads, easiest way to describe the difference is to say that Mock objects are used to define expectations i.e: In this scenario I expect method A() to be called with such and such parameters.  Mocks record and verify such expectations.  Stubs, on the other hand have a different purpose: they do not record or verify expectations, but rather allow us to “replace” the behavior, state of the “fake” object in order to utilize a test scenario.

In this case the behavior we want to stub is: “When GetCustomers() is called return the testCustomers list.”  You can see that AA version uses a Lambda expression to define the method being called.  Again the line 24 in AA version replaces lines 24-30 in R&P version.

And lastly at the end of the AAA version, as we have defined our expectation directly on the mock object itself (which replaced the record block), there is no need to define the Playback block either.  It is assumed that it follows the recorded assumptions.  Therefore the Playback section of the R&P model is comparable to Action and Assert sections of the AA model.

So as you can see our tests have dropped from 13 down to 7 lines of code.  Also due to a lot simpler mocking portion of the block tests are now lots easier to read and maintain.  I must add that this is only the portion of the new features Ayende is adding to RhinoMocks, and for more details I would refer you to go to RhinoMocks wiki as well as Ayende’s blog.  Personally I would like to congratulate him on making a good Dynamic Mocking tool great.

http://ayende.com/Wiki/Default.aspx?Page=Rhino%20Mocks%203.5&AspxAutoDetectCookieSupport=1#WhatsNewinRhinoMocksDF

 
MVC Framework CTP 2
Jeffrey Palermo has just announced that the second release of Microsoft's ASP.NET MVC Framework is available now.  Download your copy from here.
Second meeting of The Chicago Alt.Net group

This Thursday evening I met with over dozen of amazing .Net developers that share with me both excitement about future of software development and desire to learn and better ourselves.  We are all members of the AltDotNet  newsgroup and reside in Chicago area.  AltDotNet is a global movement and following is our mission statement:

We are a self-organizing, ad-hoc community of developers bound by a desire to improve ourselves, challenge assumptions, and help each other pursue excellence in the practice of software development.

Our movement is new. The conversation just started. All are welcome to shape and form the dialog in blogs and lists and face-to-face gatherings both local and global.

We met at Jaks Tap for a few hours of discussion, deciding where to go next, and how to build a community.  I am really happy to say that we are moving forward rather quickly.  We have acquired a domain for our future site already, and are in planning phases for building our web site.  Most likely we will use the "Code Camp Server", an open source project that is built using new ASP.NET MVC framework.  Few of us are also contributors to Code Camp Server.  Stay tuned for future anouncements and meantime feel free to join our mailing list.  Meantime if you wish to learn more about this movement please visit AltNetpedia.

Fluent Stubs

Refactoring has become a common practice amongst many developers I work with.  Why refactor?

Well, first it takes the pressure of off design phase of project in a sense.  You do not have spend ton of time upfront designing the code and assuring that you thought of every detail before you even write a single line of code.  You simply get a rough design and start coding right away, knowing that as you implement the system, get more familiar with the code, you will notice better patterns and refactor the code towards them.

We all know that, if done right, refactoring leads to simpler smaller code base that is easier to maintain.  Meantime we use Unit Tests to assure that the refactoring we performed did not change the outcome or results that our code produces.  I have been following this practice for a while and it has kept me out of trouble.

However what I realized over time is that the Unit Tests themselves become more complex, with too much duplication, and too hard to read.

Take for example this problem I had recently at the client I am working for.  We inherited a “failed” project (story of my life – I always end up coming in to fix someone else’s mess, but enough about that), a project that  another consulting company has given up on after complicating the matter a bit first.

No, they did not use code refactoring, they did not have unit tests, instead they have used code generation tool to “save time”.  It is just that their code generation templates were not really thought through.  Now we have a complex system, with a lot of bugs to clean and lot of code to refactor.  And yes, in order to refactor we had to start writing unit tests to support it.

Well all of their Business Objects are initialized by making a DB call in their constructor that uses Datasets as the DTOs that transfer that data from the DAL (I know what you are going to say now – but sometimes you have to work with what you have – we have to bring this site online!).

But lets start with an example.  Lets say I had a bussiness object called ShoppingCart and that it contained a list Product sand a list of Options for eaach product.  In the constructor of the ShoppingCart, they would have an instance of a ShoppingCartData object that would have a method callled ExecuteDataSet() which although the name does not state it returns all Products and their options that belong to this shopping cart.  Then the code inside of the dataset woule lop through the tables and populate both object lists, something like:

ShoppingCartData _shoppingCartData = new ShoppingCartData();

public ShoppingCart()

{

     DataSet ds = _shoppingCartData.ExecuteDataSet();

     foreach(DataRowView in ds.Tables[0].Rows){

}

 

So in order to write tests against these objects I had to mock the DAL call and replace the DataSet that the DB would return with my own.   As you can see ShoppingCartData was not injected, nor did it have an interface so for mocking part I had to bring the big guns – TypeMock. 

Mock data = MockManager.Mock(typeof(ShoppingCartData));
cartData.ExpectAndReturn("ExecuteDataSet",cartDataSetStub); 

So mocking the Db call and taking DB out of eqation was easy.  Even generating the stub data for the tests was not the problem.  You might have read one of my previos blogs where I wrote about this little code generation tool that helped me generate DataTable Stub objects just by runnig the sql :

http://www.nermins.net/post/2007/07/Mock-ADONET-with-ease-using-IDataReader-Stub-objects.aspx

In that previous example I take advantage of DataTable CreateReader() method to generate IDataReader Stubs.  However in this case my Stub objects are DataSets, so I can use these table Stubs directly.

I also have the code for that tool available on the google code site:

http://code.google.com/p/data-stub-generator/

So, if setting up mocking and setting up Stub data was not the problem then what was? I had to write a number of tests against each of the BO including Shopping Cart.  That meant setting up the data for the cartTadaSetsTub DataSet.  I also wanted my code genaration tool to generate tables with one and couple of tests records that represent the dafault /valid data, and then explicitly set the values/cells that were needed for the test in the test itself.

For example let’s say that we have the rule that says that shopping cart can not check out if there is at least on item that has been discontinued since we placed it on the shopping cart.  That means that my table returning Products data would have to have one record that has “Discountinued” column set to true.  So let’s take a look at the code needeed for that:

DataSet cartDataSetStub = new DataSet();

DataTable products = new ShoppingCartProductsStub();

products.AddDefaultRow();

products.Rows[0][“Discountinued”] = true;

DataTable options = new ShoppingCartOptionsStub();

cartDataSetStub.Tables.Add(products);

cartDataSetStub.Tables.Add(options);

Mock cartData = MockManager.Mock(typeof(ShoppingCartData));

//Assure that _shoppingCartData.ExecuteDataSet()

//returns our cartDataSetStub instead of calling DB

cartData.ExpectAndReturn("ExecuteDataSet",cartDataSetStub); 

ShoppingCart cart = new ShoppingCart(); 

Assert.That(cart.CanCheckOut, Is.EqualTo(false));  

First 7 lines of code are there just to simply setup “fake” output from the database.  There is more code in the part that sets up the data for the test than the actual test.  And actually it could have been worse if I have not used the generated table stub objects ShoppingCartProductsStub and ShoppingCartOptionsStub.  All that code crowds the test and doesn’t really expresss my intention – it is hard to read.  So what did I do to solve that?

Fluent Interfaces to the rescue!  How about this for a change:

Mock cartData = MockManager.Mock(typeof(ShoppingCartData));

cartData.ExpectAndReturn(

    "ExecuteDataSet",

     Stub.GetDataSet(

         ShoppingCartProductsStub.Empty().AddDefaultRow()

            .AtRow(0)

            .InCell(“Discountinued”)

            .SetValue(true),

         ShoppingCartOptionsStub.Empty())); 

 

ShoppingCart cart = new ShoppingCart(); 

Assert.That(cart.CanCheckOut, Is.EqualTo(false)); 

Four statements above are functionaly equivalent to that code mesh in previous example.  And as you can see you can simply read the code to figure what it does!  We are generating DataSet with two tables where on the first table we add the default row of data and then set the cell “Discontinued” to false.  Second table is empty.  And that is it.

So how do these fluent interfaces work?  What is the logic behind them?  Well simply put, lest take a look at the methods that we use to manipulate an object  (StubTable in this case).  In the example above those methods are:  Empty(), AddDefaultRow(), AtRow(int rowNo), InCell(string cellName), SetValue(object value).  Generaly these methods would return void.  In fluent programing they return the object itself or better an interface that implements these other methods.  So first I created the object called StubTable:

public class StubTable : DataTable

{

    private int _currRow = 0;

    private string _currCell = string.Empty;

    protected StubTable(){}

    public static StubTable Empty()

    {

        return new StubTable();

    }

    public StubTable AtRow(int rowNo)

    {

        _currRow = rowNo;

        return this;

    }

    public StubTable InCell(string cellName)

    {

        _currCell = cellName;

        return this;

    }

    public StubTable SetValue(object value)

    {

        Rows[_currRow][_currCell] = value;

        return this;

    }

    public StubTable AddRow(params object[] values)

    {

        Rows.Add(values);

        return this;

    } 

}

  

Then the generated SoppingCartProducts and ShoppingCartOptions DataTables inherit from Stub table and are modified to look like this:

public class ShoppingCartProductsStub : StubTable

{

    public new static ShoppingCartProductsStub Empty()

    {

        return new ShoppingCartProductsStub();

    }

    protected ShoppingCartProductsStub()

    {

        InitColumns();

    }

    private void InitColumns()

    {

        Columns.Add("ShopingCartID", typeof(Int32));

        Columns.Add("ProductID", typeof(Int32));

        Columns.Add("ProductName", typeof(String));

        Columns.Add("ProductNumber", typeof(String));

        Columns.Add("ProductQty", typeof(Int32));

        Columns.Add("Price", typeof(Decimal));

        Columns.Add("PromotionPrice", typeof(Decimal));

        Columns.Add("Discontinued", typeof(Boolean));

       

    }

    public StubTable AddDefaultProduct()

    {

        Rows.Add(705582, 1,

                "Round Cook-N-Dine Built-in Cook Top", "MO-60", 5,

                decimal.Parse("1200.9400000000000"),

                decimal.Parse("1200.9400000000000"),false);

        return this;

    }

}

 

And Finaly Our Stub class that builds and returns the DataSet DTO:

public class Stub

{

    public static DataSet GetDataSet(params DataTable[] tables)

    {

        DataSet ds = new DataSet();

        foreach (DataTable table in tables)

            ds.Tables.Add(table);

        return ds;

    }

} 

The conclusion I would draw from this is that with a little thinking upfront, and a little refactoring we can make our tests a lot more readable.  We always have to keep in mind that our tests might be the first thing that the next developer is going to look at.  Making the test little bit more readible helps them figure out easier on how the actual object being tested is used and what are the expectations set for it.

 

kick it on DotNetKicks.com

Resharper 3.1 + Visual Studio 2008

As most of us Resharper enthusiasts know current version 3.1 does not work well with Visaul Studio 2008.   To be more specific, some of the C# 3.0 features like Extension methods and Lambda Expressions "confuse" Resharper and it ends up reporting that as a syntax error, where it is just a new language feature. 

Visual Studio 2008 code file with extension methods and Lambda expressions with Resharoer 3.1 turned on

From the image above you can see the effects of that.  However there is a ReSharper shortcut key which allows us to turn of ReSharper validation only for current file being edited.  If you press "Ctr+8" you will turn off/on ReSharper validation on file being currently edited.  Since I do not have Labmda expresions in each code file in my project this feature allows me to still use ReSharper for VS 2008 projects.

Bellow is the screen shot of the same code file after pressing Ctr+8:

 

VS 2008 with ReSharper turned off
Number of Scaffolding options grows in MVC for ASP.NET

As most of you already know Scott has announced that the Dynamic Data (see screencast) is going to have an MVC compatible version.

It appears that Rob Conery and SubSonic team have worked on MVC compatible version of SubSonic code-named Makai.

As you can see from the screen bellow, they implemented a ScaffoldController<T>, where T is a "model" portion of the MVC.  By inheriting from ScaffoldController<T> and declaring your model class, Makai framework implements all of the Create, Update, Delete, List actions for your controllers and generates dynamic views.  Therefore creating a prototype is a breeze.

I  do understand that a lot of MVC purist do tend to ignore the Scaffolding portion of the MVC, but it is a necessary evil.  MVC is a new technology in .Net world and it is hard to sell it to many IT managers.  But sometimees when they see how rapidly we develop a prototype  they might consider looking further.

Same as dynamic data, Makai generates a set of initial templates, that the list,edit and update views are using.  These templates can be overriden/modified and that is one way for us to get some flexibility in a defining the layout of the views in a prototype.

In addition to that, since Makai implementation is based on the controller, we simply can enrich the functionality by adding the new Actions/Views to our ScaffoldingController class.  This allows us to "evolve" the prototype into the product over time, instead of having to drop all of the prototype and start from scratch.

For more details on Makai please visit Ron Conery's blog here.

ScaffoldController 

Vista + IE7 + Google Toolbar + Akamai download manager = download trouble

So far I have been running VS 2008 Beta from a VPC image.  Since few of my friends told me that they had no problem running this beta version next to the VS 2005 I finally decided that it is ok to download this version and install it to my host OS.

So, I simply go to MS site select the Visual Studio image for download (hefty 3.2 GB), and start the process.  First thing I notice is that the download link installs the Akamai download manager ActiveX control.  This seems to be a good thing, since the download manager opens 4 separate connections, and starts main download using full bandwidth of my DSL connection, transferring at 250 Mb per second.  Even at that speed I am nearly 4 hours away from the completed download.  But that is ok - I choose desktop folder as the destination for the downloaded file.

Four hours later I am in front of my laptop.  Akamai download manager reports download as complete.  Great!  I take a look at the desktop - the file is not there?!  I try to refresh it, open the folder in the windows explorer. There is no file!  OK it must be some weird Vista security permission, or something....  Maybe the file is put in temp folder.  Nope, not there.  OK, I am going to use the "awesome" live search to find this file.  

Twenty minutes later after trying multiple search criterias (searching by date, size, name...), I finally give up.  There must be something wrong with downloading to the desktop.  I am going to try downloading to the "My Documents folder".  Four hours later, same results - no file!  What is going on. 

I finally decide to explore the issue through couple of Google searches.  It appears that few folks have experienced the same problem.  None of them have figured out the real cause, but have noticed that Mozilla downloads the file without problem.  I open up my Mozilla browser, copy the download link into it.  First difference - this time the Akamai download manager is an applet, not an ActiveX control.  Second, and more important difference is that prior to selecting a destination folder, I do get a "Pop-up blocked" message - I change it to allow pop-ups.  The download works fine - the whole file is downloaded to the desktop.

Scott shares some thoughts about MVC framework for ASP.NET on his web site

Well, it seems that man himself has spoken about details of this upcoming framework.  He has given us a timeline as well as what the framework encompasses.  What I find interesting is that it seems that Microsoft is not just building a "copy" of an open source project, replacing all of the Open Source libraries with their own, but actually building a framework that can interoperate with OpenSource libraries.

In other words, you are not limited to ObjectBuilder as an IoC container, you will be able to plug in Spring.Net, or Windsor, nor you are limited to MSTEST when it comes to unit testing.  I am truly surprised by these news from Microsoft.  Congratulations to Scott and his team.

Scott's post can be found at:

http://weblogs.asp.net/scottgu/archive/2007/10/14/asp-net-mvc-framework.aspx

Why Javascript is BAD!!!

Just logged into my Google email account.  I have a list of dozen or so chained emails (bunch of replies between me and few of my coleques).  Expanding one of the replies (they are inside colapsible regions), revelead the error bellow:

Now who would debug auto generated script file of 173 million lines of code?  Enough with the AJAX nonsense! It is time to take a look at Silverlight (1.1 that is - the one with DL runtime)!

Free Ruby on Rails book

Friend of mine has forwarded me this link:

http://www.sitepoint.com/books/rails1/freebook.php

It is over 400 pages of material on Ruby and Rails by Patrick Lenz.  You can download it as a free PDF.  Keep in mind it is a 21MB download.  Enjoy reading it!  I know I will.

Scott Guthrie announces ASP.NET MVC framework at Alt.Net Conf

I have had several moments in my career where I was near a point of just simply giving up on MS and joining the "other side".  I remember the time few months before .Net 1.0 was released.  Java camp was leading the development world with innovations, while MS kept trying to persuade us that VB/COM was the way to go.  At that time I even joined the Java team at my company almost entirely making a switch.   

Then I was given an opportunity to review technologies for complete replacement of one of the ASP sites, project I was assigned to lead.  I evaluated obviously ASP, JSP, and soon to be released ASP.Net (learning C# at the same time).  And the thing that stroked me then was: "My God, sleeping giant has awaken!"  There was no question in my mind that C#/.Net was not a mere Java clone, but a well thought of framework and language that went one step further.  In addition there was nothing like ASP.NET available on the market.   

We started on the project the week .Net was released.  Completed it month ahead of schedule.  I stayed in MS camp.  

Another moment was just recently.  For any of you that read my blog you will know that I am really big fan of the Agile process and specifically Test Driven Development.  One of the problems with the TDD is being able to write/define tests/behaviors throughout your code including all layers of the application.  And we all know that sometimes UI code can prove virtually untestable.  That is where flavors of MVC/MVP patterns come in.  They help us solve that problem.  

MVC being doable in windows forms (using IoC, and frameworks like CAB), it was nearly impossible to accomplish it in the ASP.NET web development.  

That is when I saw my first demo of Ruby on Rails.  Everything that was missing, or done wrong in ASP.NET was implemented right in Ruby.  No huge configuration files, XML that "generates", code, source code versioning and schema migration are coordinated.  Schema is defined in one place only.  OR Mapping and the ActiveRecord pattern implemented flawlessly.  Ruby uses a true MVC implementation.  And it is all easy to learn and implement.  And productivity gained in developing, maintaining, migrating/updating, deploying these web apps is enormous.  

These concepts have been around for a few years.  Loads of Java folks and already some of the .Net folks are moving into Rails development.  Yet Microsoft stayed quiet about this, having virtually none of these features in upcoming VS2008.   

And right about time I am truly about to give up on MS altogether, I read this post from Jeffrey Palermo about an announcement of the MVC framework Scott Guthrie and his team are working on to be released as an add-on to the VS 2008.  Here are the goals of that project:

·  Natively support TDD model for controllers.

·  Provide ASPX (without viewstate or postbacks) as a view engine

·  Provide a hook for other view engines from MonoRail, etc.

·  Support IoC containers for controller creation and DI on the controllers

·  Provide complete control over URLs and navigation

·  Be pluggable throughout

·  Separation of concerns

·  Integrate nicely within ASP.NET

·  Support static as well as dynamic languages  

 

Folks familiar with MonoRail might say that there is all that built in the MonoRail project and lot more (ActiveRecord, Windsor, etc), and I agree with that.  But having all this come from Microsoft (with all of the visibility that comes with it), can only be a good thing.  I applaud Scott and his team - this is what I and bunch of the folks I know have been waiting for.  And yes, I think I will stay in MS camp for a while now.

Another day in Infragistics world

For all of us who have been unlucky to work with Infragistics controls, there comes a time where we say enough is enough! Where do I start?  Their archaic object model is horrible. 

Lets say you are using Ultra(complicated)Grid, and try to set an attribute of a row, or a column, be it width, color something else?  How do you think you would go about doing that?

Maybe  UltraGrid has Rows and Columns collections where all the properties related to a specific one can be set?  Not likely!  More likely you will have to go into UltraGrid.DisplayLayout, or maybe UltraGrid.Override. ...  But perhaps it is UltraGrid.Bands[..]...How about all those Appearance objects crowding the designer code and being trully randomly generated? 

That is the type of code that brings Source Control merge down to its knees.  And naturaly in case that 2 developers, God forbid, worked on a same screen containing Infragistics controls - due to the Apearances merger issues, your from designer is going to crash next time you perform "Get Latest". 

But that is not the topic I want to discuss today.  The problem is much more simple but yet somehow more irritating.  So I have had a control that inherits from UltraCombo.  Lets call this control NerminsCombo.  I had to define a behavior that happens each time value is selected in the dropdown of Nermin's combo.  So far simple.So I find a protected RowSelected event.  Obviously I am not about to register RowSelected event handler in the control that fires the event.  As we all know all controls have protected methods that are in charge of firing the events and their signature always is On[Event Name].

I guess I am lucky because I find the protected OnRowSelected() method right away.  So I override it, calling the base.OnRowSelected() first and then my implementation.  Then I run a quick test, and....   nothing happens.  I put the break point and it does not get hit.  WTF! 

An hour later, and after trying several different options, googling for possible blog entries about a bug in Infragistics, I finally registered an event handler to the RowSelected in the form that was using NerminCombo.  That handler got called but at the same time the code in the OnRowSelected override was executed.So OnRowSelected was only called if there were registered event handlers to RowSelected. 

So obviously this method was not firing the RowSelected event.  Using one of my favorite tools – Reflector, I disassembled the code of the UltraCombo and took a look at it. 

Finally after all this I discovered another protected method called FireRowSelected.  Like its name stated it was the method that was in charge of invoking RowSelected event.  Overriding this method produced desired results – defining a behavior that is executed inside the NerminCombo each time a selection of the row was made.

Now comes the question – why would Infragistics not follow control design recommendations from Microsoft?  Does the design of this control pre-dates .Net?  If that is the case, why wouldn’t they note this discrepancy in their help documentation?  And why do I have to waste my time on things like these each time I write code that depends on Infragistics controls?

Mock ADO.NET with ease using IDataReader Stub objects

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.

TDD/Using Mock objects with CSLA.Net (Round II)

I have received few comments on the first post, one of them being from Rocky Lhotka the creator of the Csla.Net framework.  He basically pointed to his advanced data sample (DeepData.sln available for download at www.lhotka.net).  The idea is that if we encapsulate all of the ADO.NET constructs required to fetch/update a single table into a “Data object” and move it from the Fetch() method of Csla object (some might find this similar to Table Data Gateway pattern), then the only thing we have to mock is that Data object.  In addition setting expectations would be lot simpler, since everything is encapsulated.  So, instead of me talking about it lets look at how that changes the Fetch method of the ProjectList class defined in PTracker sample:

private void Fetch(string nameFilter)

{

    RaiseListChangedEvents = false;

    DataFactory df = new DataFactory();

    using(ProjectListData data = df.GetProjectListDataObject()) {

        SafeDataReader dr = data.GetProjectList();

        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;

}

Code above is simpler than the original or the refactored code I had (only a single using block, and no ADO.NET dependencies) .  So lets take a look at what happened.  We stopped using the Database class (that functionality will move into our Data object – ProjectListData).  We can see 2 new objects constructed in this code:

1.       DataFactory – Factory in charge of instantiating all of the Data objects for our project

2.       ProjectListData – Data object, whose purpose is to encapsulate the ADO.NET constructs, and return a SafeDataReader back to the Ftech() method.  It is imprtant to note that ProjectListData implements IDisposable interface.  That way as we dispose of it, it will dispose corresponding DataReader, DbCommand and a Connection.  Hence only one using block needed here.

Test are then as simple as:

[Test]

public void LoadsOne()

{

    Mock mockProjectListData = MockManager.Mock(typeof (ProjectListData));

    mockProjectListData.ExpectAndReturn("GetProjectList",

        new ProjectListFetchOneDRStub().GetDataReaderStub());

    mockProjectListData.ExpectCall("Dispose");

    ProjectList item = ProjectList.GetProjectList();

    Assert.AreEqual(1,item.Count);

}

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

public void LoadsThreeFiltersTwo()

{

    Mock mockProjectListData = MockManager.Mock(typeof(ProjectListData));

    mockProjectListData.ExpectAndReturn("GetProjectList",

        new ProjectListFetchThreeDRStub().GetDataReaderStub());

    mockProjectListData.ExpectCall("Dispose");

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

    Assert.AreEqual(1, item.Co