Monday, July 11, 2011

Master Pages Refactored

The master pages have been refactored.  There are now two levels of master pages.

Page.Master is the top level master page that contains most of the structure, script, links, etc.

MvcSite-NoSummary.Master, MvcSite-WideSummary.Master and MvcSite.Master inherit from Page.Master and do the following:

1. Reference different style sheets
2. Repeat content place holders that the actual pages need from Page.Master
3. Add layout structure for the right panel if needed

Friday, July 8, 2011

Removing Duplicate Transaction Management Code

There is a method called WrapInTransaction on RemotingObjectBase that you should use to add transaction management to code in the remoting facade.

Instead of writing

public void RaiseBirthdayEvents ()
{
    StartTransaction (IsolationLevel.ReadCommitted, "RaiseBirthdayEvents");
    bool committed = false;    

    try
    {
        List<int> personIds = Accessors.PersonDA.FetchPersonIdsByBirthDt (Services.DateService.Today.Month, Services.DateService.Today.Day);            
        foreach (int personId in personIds)
        {
            Services.EventingService.RaiseEvent (EventType.Birthdate, Services.DateService.Today, Table.Person, personId);
        }        

        CommitTransaction ();
        committed = true;
    }
    finally
    {
        if (!committed)
        {
            RollbackTransaction ();
        }
    }
}

you can now write
public void RaiseBirthdayEvents ()
{
    WrapInTransaction ("RaiseBirthdayEvents", () => 
    {
        List<int> personIds = Accessors.PersonDA.FetchPersonIdsByBirthDt (Services.DateService.Today.Month, Services.DateService.Today.Day);

        foreach (int personId in personIds)
        {
            Services.EventingService.RaiseEvent (EventType.Birthdate, Services.DateService.Today, Table.Person, personId);
        }
    });
}

Similarly if the code being wrapped needs to return a value, then
public int CreateProlinkManualApplication ()
{
    bool committed = false;
    StartTransaction (IsolationLevel.ReadCommitted, "CreateApplication");

    try
    {
        ApplicationEntity application = ApplicationEntity.Create ();
        application.SaleSourceId = (int) SaleSource.ProsperityApplicationForm;
        Adapter.SaveEntity (application);

        CommitTransaction ();
        committed = true;

        return application.ApplicationId;
    }
    finally
    {
        if (!committed)
        {
            RollbackTransaction ();
        }
    }
}
becomes
public int CreateProlinkManualApplication ()
{
    return WrapInTransaction ("CreateApplication", () =>
    {
        ApplicationEntity application = ApplicationEntity.Create ();
        application.SaleSourceId = (int) SaleSource.ProsperityApplicationForm;
        Adapter.SaveEntity (application);                                               

        return application.ApplicationId;
    });
}
Finally here is the code for the two overloads of the wrapping method:
protected void WrapInTransaction (
    string transactionName,
    Action action)
{
    StartTransaction (IsolationLevel.ReadCommitted, transactionName);
    bool committed = false;

    try
    {
        action.Invoke ();

        CommitTransaction ();
        committed = true;
    }
    finally
    {
        if (!committed)
        {
            RollbackTransaction ();
        }
    }
}

protected T WrapInTransaction <T> (
    string transactionName,
    Func<T> function)
{
    StartTransaction (IsolationLevel.ReadCommitted, transactionName);
    bool committed = false;

    try
    {
        T result = function.Invoke ();

        CommitTransaction ();
        committed = true;

        return result;
    }
    finally
    {
        if (!committed)
        {
            RollbackTransaction ();
        }
    }
}

Thursday, July 7, 2011

Mocking LlblGen RetrievalProcedures

If you need to create a mock for one of the LlblGen classes such as RetrievalProcedures, you are faced with the problem that there is no interface for you to use.  Fortunately most of the classes generated by LlblGen are partials so you can use add your own code to them.

Suppose you need to mock out RetrievalProcedures and that it has a method called GetPins you want to mock:

public partial class RetrievalProcedures
{
    public virtual DataTable GetPins(System.Int32 numberOfPins)
    {
        using(DataAccessAdapter dataAccessProvider = new DataAccessAdapter())
        {
            return GetPins(numberOfPins, dataAccessProvider);
        }
    }

    public virtual DataTable GetPins(System.Int32 numberOfPins, IDataAccessCore dataAccessProvider)
    {
        using(StoredProcedureCall call = CreateGetPinsCall(dataAccessProvider, numberOfPins))
        {
            DataTable toReturn = call.FillDataTable();            
            return toReturn;
        }
    }

    ...
}

You can create a partial class next to it as well as the interface you need and let the partial class implement the interface:

public interface IRetrievalProcedures
{
    DataTable GetPins(System.Int32 numberOfPins);

    DataTable GetPins(System.Int32 numberOfPins, IDataAccessCore dataAccessProvider);
}

partial class RetrievalProcedures : IRetrievalProcedures
{
}

The original class now implements the new interface and you can go forth and mock.

Enums: The Dark Side

In a previous post I advocated using enums as much as possible.  There are however times when this is not a good idea.

If a lookup table requires the ability to easily add new lookup values without redeploying the code base, you should avoid using enums in data accessors, view models, etc. 

The situation we had involved document types. After adding a new document type, the code had to be updated.  This shouldn't be necessary in this case and should have just worked.

So as with most things, use common sense.  I suggest keeping a list of lookups that should not be dealt with using enums for your project.

Unit Testing Private Methods

Sometimes you want to write a unit test against a private method. 

First let me say that most of the time this is an indication of a design problem.  Rather consider whether your class really wants to be more than one class or whether you should be testing the code indirectly using one of the other public methods of the class.

If you are convinced you really want to write a unit test for the private method, there is an alternative to calling the method using AsDynamic ().  The problem with AsDynamic () is that you lose all the benefits of strong typing, including support for refactoring.

Lets say you have a class called Class1 like this:

public class Class1
{
    private void Method1 ()
    {
    }
}

In order to call Method1 you can change Method1 in Class1 to protected and create a testing subclass like this:

public class TestClass1
    : Class1
{
    public void TestMethod1 ()
    {
        Method1 ();
    }
}

In your tests you can then create an instance of TestClass1 and call TestMethod1.

Wednesday, July 6, 2011

Configuring Moq to return different results

If you need to create a mock that can return one result the first time and another the second time, you can use the MoqExtensions class like this:

MockPremiumCalculationService = new Mock<IPremiumCalculationService> ();
PremiumCalculationResponse response1 = new PremiumCalculationResponse ();
response1.Premium = 55;
PremiumCalculationResponse response2 = new PremiumCalculationResponse ();
response2.Premium = 60;
MockPremiumCalculationService.Setup (
    pcs => pcs.Calculate (It.IsAny<PremiumCalculationRequest> ()))
    .ReturnsInOrder (response1, response2);

For more info see this article by Phil Haack:

http://haacked.com/archive/2009/09/29/moq-sequences.aspx

Tuesday, July 5, 2011

Data Access from LD.FunctionalTest

Instead of writing a separate query for each entity in your test class e.g.
       
private List<PremiumEntity> FetchPremiums(
    params int[] policyIds)
{
    LinqMetaData metaData = new LinqMetaData(Adapter);
    var query = (from p in metaData.Premium
        where policyIds.Contains (p.PolicyId)
        select p);
    return query.ToList();
}

there is now a method on LinqMetadata you can use along with a property called MetaData on the TestBase class.The above code can now be replaced by a call inside your test that looks like this:

List<PremiumEntity> partnerPremiums = MetaData.GetEntities<PremiumEntity> ();

Similarly you can get the number of entities in the database by calling

List<PremiumEntity> partnerPremiums = MetaData.GetNumEntities<PremiumEntity> ();

Note that you don't need to get the number of entities in the database at the start and compare them with the number at the end because we always start with a clean database.