Unit Testing in Csla.Net

Unit Testing in Csla.Net

Old forum URL: forums.lhotka.net/forums/t/2801.aspx


nermin posted on Monday, April 30, 2007

I have recenlty posted a blog article on my implementation of unit testing with Csla, views on Test Driven Development and a usage of the TypeMock dynamic mock library that helped me generate some of my tests.

I would like to hear from feedback from folks that had more expirience with Csla than I have, as well as alternative approaches to Unit Testing with Csla.

Original post can be found here:

http://www.nermins.net/PermaLink,guid,d9a9fa9c-a700-4157-9c5e-59119bf0ea08.aspx

Regards,

Nermin 

the.next.peter.parker replied on Tuesday, May 08, 2007

personally i would move the data access outside of the business object and replace the DataPortalXXX methods with calls to a factory that would call the right data provider.  the dal would return an interfaced dto.

so when you go to test the business object, you could set up a mocked or dummy provider to test your business object with for things like behavior, business logic, custom validation, etc. 

i think maintaining seperate code layers (not to be confused with physical tiers), imho, make things cleaner, easier to extend, much easier to test and you're back to the an object should really only do one thing/have one purpose rule.  (plus this might make it easier to switch your objects to using linq later, which is a bonus, but should not be your main reason for creating layers at this point).

another thing is that i would not use the Sqlxxxx objects (in example SqlDataReader) but use the interfaces in the System.Data namespace like IDbParameter etc, that way you can easily switch between database providers, not to mention most mock libraries utilize interfaces for mocking purposes.

notice that SafeDataReader takes an object that implements the IDataReader, which is pretty smart on rocky's part so that you can easily user datareaders from other providers that extend from those interfaces like the mysql connector for .net.

RockfordLhotka replied on Tuesday, May 08, 2007

Also, if you look at the DeepData sample from my site you can see a technique by which you can externalize the opening of the database connection, the setup of the command and the creation of the datareader. Then the business object only deals with a pre-opened datareader.

This is relatively easy to mock, because you can create a mock object that doesn't open a db or command, but does create a mock datareader with test data, so your object is populated from it.

Same concept can work for insert/update - though obviously the data goes into the ether because there's no actual database.

nermin replied on Wednesday, May 09, 2007

Rocky, “the.next.peter.parker” I would like to thank you both on your recommendations.  Looking at how it simplifies mocking process, I couldn’t stop thinking “How come I didn’t think of this?”  But hey, this is why we post issues we have to newsgroups.  Following your example (I did not use the one with DTOs – too much coding for me, without any obvious advantages I can see at this time) I modified the code in the PTracker sample under  ProjectList Fetch() to see what I get from this:

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) Test is 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);

}

Basically I just mock the ProjectListData and assure that I replace the SafeDataReader returned by “ProjectListData” object with the one I need for the test (one created by ProjectListFetchOneDRStub().GetDataReaderStub()).  Second expectation is assuring that the Dispose() is called on ProjectListData object.

As far as the recommendation to not use Sqlxxx objects but generic interfaces instead,  I generally use Enterprise Library DAAB as my data access library which does that for me.  In that example I was just refactoring the original PTracker project which had Sqlxxx implementation which I did not modify for simplicity and easier of comparison to the original.

Thanks,

Nermin

Copyright (c) Marimer LLC