Using StructureMap to mock DataAccess in CSLA BO

I had always thought StructureMap is just another IOC tool similar to Castle windsor, until yesterday I read Karl Seguin’s Foundations of Programming, Chapter 4, I was shocked immediately by the injectStub method provided by StructureMap, which is now renamed to inject(). I think this explicitly injection is better than TypeMock implicitly mock instance object.

For example, I have an Organization BO,


public static OrganizationBO GetOrganizationBO(int Id)
{
return DataPortal.Fetch<OrganizationBO>(new SingleCriteria<OrganizationBO, int>(Id));
}

private void DataPortal_Fetch(SingleCriteria<OrganizationBO, int> criteria)
{
OrganizationDTO data = DataAccess.OrganizationRepository().FindById(criteria.Value);

if (data != null)
{
LoadFromDTO(data);
}
}

The repository is declared in DataAccess class to centralize all the dataaccess coupling inside CALS BOs.


public static IRepository<OrganizationDTO> OrganizationRepository()
{

// instead of direct coupling return new OrganizationRepository();
// I use StrcutureMap
return ObjectFactory.GetInstance<IRepository<OrganizationDTO>>();
}

The content of IOC config file:

<DefaultInstance
PluginType=”DemoApp.Data.Interfaces.IRepository`1,DemoApp.Data”    PluggedType=”DemoApp.Data.Repository.OrganizationRepository,DemoApp.Data”
/>

We can also use other different ways to set dependency, like setDefault in code, or search assembly at  runtime as shown in this post.

Test  code:


[Test]
public void CanGetFromInjectedMockRepository()
{
var mockRepository = new Moq.Mock<IRepository<OrganizationDTO>>();

// Id in MoQ matters. But TypeMock doesn't care.
mockRepository.Expect(x => x.FindById(8172)).Returns(
new OrganizationDTO
{
Id = 1,
Name = "A test org name"
});

ObjectFactory.Inject(typeof(IRepository<OrganizationDTO>), mockRepository.Object);

var o = OrganizationBO.GetOrganizationBO(8172);

Assert.AreEqual(1, o.Id);
Assert.AreEqual("A test org name", o.Name);
}

Here is an artile introducing StructureMap, as it mentioned, StrucutreMap is very good choice if you are working on a class has no “constructor injection”, CSLA is one of those!

I have the same feeling, as the author Karl Seguin said, constructor injection doesn’t really solve the extensibility problem; how does someone add(try to replace) a new plug-in without recompiling the entire application?

The problem/drawback to DI is also obvious, the xml config file keeps growing and expanding. The performance and mantiance will become an issue. That’s why Boo was inverted to save / speed up Castle Windsor. But what about structure Map?

Also I need tool / method to test this xml config file, see details here and here. Unfortunately, I couldn’t make this <structuremap.verification> task loaded into NAnt, (maybe this doesn’t exist in those two dlls at all? I can’t tell because NAnt loadTask doesn’t have output). I tried to different folders and also “Forced scan” using <loadtasks> command, neither one works. Thanks God, Jeremy does have another way to test config file,so called smock test:

ObjectFactory.AssertConfigurationIsValid();

Regarding unit-test and mock, I spent a lot time trying to figure out how to reset the default back. It turns out the documented ObjectFactory.resetdefault has been changed to reset.

Advertisements

Test Authorizatoin Rules in CSLA

To test CSLA BO’s authorization settings, I have to mock the IPrincipal.IsInRole method, RhinoMock example like this:

        [Test]
        [ExpectedException("System.Security.SecurityException")]
        public void CanHideForUnAuthorizedUser()
        {
            MockRepository mocks = new MockRepository();
            IPrincipal mockPrincipal = (IPrincipal)mocks.CreateMock<IPrincipal>();
            Csla.ApplicationContext.User = mockPrincipal;

            using (mocks.Record())
            {

                Expect.Call(mockPrincipal.IsInRole("user")).Return(false);

            }// Replay and validate interaction
            Order obj = null;
            using (mocks.Playback())
            {
                obj = Order.GetOrder(new Guid("c512e473-19fd-401c-80f6-055cf239e461"));

            }// Post-interaction assertions
            Assert.IsNull(obj);

        }

         [Test]
        public void CanGetOrderUsingTypeMock()
        {

            // Setup Stud Data to be returned from mocked repository.
            // This code could be moved into record expectation block
            // but we assume everything inside that block is mocked.
            // to reduce confusion, just leave it here.
            // In fact , this mode is faster comparing the other one.
            OrderDTO stubOrderDTO = new OrderDTO();
            stubOrderDTO._OrderNumber = "12345";

            // Everything inside recorder block will be mocked.
            // expect the settng return value line: recorder.Return()
            using (RecordExpectations recorder = RecorderManager.StartRecording())
            {
                // Don't have to mock the IPricipal object "User"
                // Here TypeMock is too powerful. no need to think.
                Csla.ApplicationContext.User.IsInRole("user");
                recorder.Return(true);

                OrderRepository mockRepository = new OrderRepository();
                mockRepository.GetById(Guid.Empty);
                recorder.Return(stubOrderDTO);
            }

            Order p = Order.GetOrder(Guid.Empty);
            Assert.IsNotNull(p);
            Assert.AreEqual("12345", p.OrderNumber);
        }

After using typemock for a while, I suddenly tired of Rhino’s record-play syntax, looking into MoQ’s doc, it’s very similar to TypeMock, but it’s LinQ syntax (var and Lamba) are only available on 3.5 framework.

If using MoQ, the Rhino example will shorten to:


       [Test]
        [ExpectedException("System.Security.SecurityException")]
        public void CanHideForUnAuthorizedUser()
        {
            var mock = new Mock<IPrincipal>();
            mock.Expect(x => x.IsInRole("user")).Returns(true);
            Csla.ApplicationContext.User = mock;

            var obj = Order.GetOrder(new Guid("c512e473-19fd-401c-80f6-055cf239e461"));
        }

TypeMock Repository object in CSLA BO

CSLAEx DAL’s basic idea is adding an middle method in DataPortal_XXX():

CSLA BO Get -> DataPortal_Fetch -> DataAccess.ReadDataMethod (return SafeDataReader)

I added another repository in between to introduce stong type domain object instead of DataReader (I think DataReader is not much difference than DataSet in UI)

CSLA BO Get -> DataPortal_Fetch ->Repository.DataProssingMethod() (return DTO)-> DataAccess.ReadDataMethod (return SafeDataReader)

Repository can be mocked, and DataAccess can be tested (based on peeking into db then writing assert expection.)

The next problem is, how to test / mock the top level static Get method? I tried using adapter pattern by adding a injectable public constructor to BO, then the test case code like this:

[Test]
public void GetProductOnBOTestUsingMock()
{
MockRepository mocks = new MockRepository();
IProductRepository mockRepository = (IProductRepository)mocks.CreateMock<IProductRepository>();
Product p = new Product(mockRepository);
Guid id = Guid.NewGuid();
using (mocks.Record())
{
ProductDTO fakeProduct = null;
Expect.Call(mockRepository.GetById(id)).Return(fakeProduct);

}// Replay and validate interaction
Product obj = null;
using (mocks.Playback())
{
obj = p.GetProductAdaptor(id);

}// Post-interaction assertions
Assert.IsNull(obj);

Assert.AreEqual(obj.ProductName, "");
}

This test case failed, because in CSLA’s calling sequence:

Client.DataPortal -> LocalProxy -> Server.DataPortal -> 1. ServicedDataPortal TransactionalTypes.EnterpriseServices: 2. TransactionalTypes TransactionalTypes.TransactionScope 3. SimpleDataPortal default

The last step will run this piece of code:

namespace Csla.Server
{

public class SimpleDataPortal : IDataPortalServer
{
public DataPortalResult Fetch(Type objectType, object criteria, DataPortalContext context)
{
object obj = null;
try
{
// create an instance of the business object.
obj = Activator.CreateInstance(objectType, true);
...

My attempt to adding constuctor injection won’t suceed. I had to back to TypeMock then:

[Test]
public void TestGetUsingTypeMock()
{
// Setup Stud Data
ProductDTO stubProdDTO = new ProductDTO();
stubProdDTO.ProductName = "TypeMocked prod name";

// Everything inside recorder block will be mocked.
// expect the last line settng return value.
using (RecordExpectations recorder = RecorderManager.StartRecording())
{
ProductRepository mockRepository = new ProductRepository();
mockRepository.GetById(Guid.Empty);
recorder.Return(stubProdDTO);
}

Product p = Product.GetProduct(Guid.Empty);
Assert.IsNotNull(p);
Assert.AreEqual("TypeMocked prod name", p.ProductName);
}

It’s green

Another benefit to add a repository between BO and DataAccess object might be, it will be easier to use Castle’s IIntercepter to log those repository calls. As Castle warned:

If you are registering a component without an interface (the service) then only virtual methods can be intercepted.

Miguel seems doesn’t like code against interface in his dataaccess class, neither does Rocky in his CSLA BO. But we can add interface in our repository object. I am going to post this part of code once I finish it.

About repository class, JP treats those classes as DataAccess objects which makes sense, the return type of his repository class is Domain object, so he convert those domain object to DTO in his task layer using mapper class (Martin Fowler initially uses XXXAssembly class to do the conversion between domain object and DTO) Our CSLA BO is too rich which can not be returned from repository, so my repository just returns DTO instead. I think this solution can eliminate the usage of task and mapper object in my project.

Mock / stub CSLAEx safeDataReader class

Miguel’s CSLAEx provides a very good DAL for CSLA BL. The DataAccess class wraps all the db calls then make data portal function in BL much simpler.

public SafeDataReader ProductGetById(Guid productID)
{
IDataParameter[] parameters =
{
GetParameter("@p_ProductID", productID) as IDataParameter
};

return GetReader("ProductGetById", CommandType.StoredProcedure, parameters);
}

So the BO data portal becomes to this:

protected void DataPortal_Fetch(IdCriteria<Guid, Product> crit)
{
using( SafeDataReader sd =
new DataAccess().ProductGetById(crit.ID))
{
if (sd.Read())
{
_ProductID = sd.GetGuid(sd.GetOrdinal("ProductID"));
_ProductName = sd.GetString(sd.GetOrdinal("ProductName"));
_Description = sd.GetString(sd.GetOrdinal("Description"));
}
}
}

I am very pleased to see he has the same motion to move those sql plumbing code out of BO, but, why do we still see SafeDataReader here. The worse thing is, we have to call SafeDataReader.Read() again to fetch the real data.

I made some modifications then:

public class ProductRepository
{
private DataAccess _DAO = null;

public ProductRepository() : this(new DataAccess()) { }

public ProductRepository(DataAccess dao)
{
_DAO = dao;
}

public ProductDTO GetById(Guid productID)
{

ProductDTO p = new ProductDTO();

SafeDataReader sd = _DAO.ProductGetById(productID);
if (sd.Read())
{

p.ProductID = sd.GetGuid("ProductID");
p.ProductName = sd.GetString("ProductName");
p.Description = sd.GetString("Description");

}

return p;
}

[Serializable()]
public class ProductDTO
{
public Guid ProductID = Guid.Empty;
public string ProductName = String.Empty;
public string Description = String.Empty;
public string DownloadFile = String.Empty;
public decimal UnitPrice = 0;

public ProductDTO(){}

}

public class Product : BusinessBase<Product>
{
private Product() { }

protected override object GetIdValue()
{
return _Data.ProductID;
}

private ProductDTO _Data = new ProductDTO();

[DataObjectField(true, true)]
public Guid ProductID
{
get
{
CanReadProperty("ProductID", true);
return _Data.ProductID;
}
}

public string ProductName
{

get
{
CanReadProperty("ProductName", true);
return _Data.ProductName;
}

set
{
CanWriteProperty("ProductName", true);
if (value != _Data.ProductName)
{
_Data.ProductName = value;
PropertyHasChanged("ProductName");
}
}
}
....
protected void DataPortal_Fetch(IdCriteria<Guid, Product> crit)
{
_Data = new ProductRepository().GetById(crit.ID);
}

protected override void DataPortal_Insert()
{
new ProductRepository().Insert(_Data);
}

protected override void DataPortal_Update()
{
new ProductRepository().Update(_Data);
}

The benefit of this change is, ProductRepository is testable, and injectable. By switching DataAccess class to Linq2Sql DataContext class (using IDataAccess instead), the Repository and BO class won’t need to change too much.

I am disappointed he has less interest in TDD, including DDD. Why do we need this Command Object in CSLA? Can Domain object solve those sql query in a much simpiler way?

Have not learn CSLA’s parent-child yet, but I already got a feeling, CSLA is not good at relationship.

Validation is great, rules can be in 3 different levels, Information, Warning and Error. Also can be stopped by setting a flag. What a thoughtful business framework!

Tried to test those data methods.

[TestFixture]
public class ProductRepositoryTest
{
[Test]
public void GetProductOnBOTestWithoutMock()
{
Product obj = Product.GetProduct(new Guid("309e8408-2d22-45f9-82aa-01a7884c0603"));

Assert.AreEqual(obj.ProductName, "HP Laptop");
}

[Test]
public void GetByIdTestOnRepositoryWithoutMock()
{
ProductRepository r = new ProductRepository(new DataAccess());

ProductDTO p = r.GetById(new Guid("309e8408-2d22-45f9-82aa-01a7884c0603"));

Assert.AreEqual(p.ProductName, "HP Laptop");
}

[Test]
public void GetByIdTestOnRepositoryUsingMock()
{
MockRepository mocks = new MockRepository();
ITrainingDataAccess mockDao = (ITrainingDataAccess)mocks.DynamicMock<ITrainingDataAccess>();

ProductRepository r = new ProductRepository(mockDao);

Guid id = new Guid("309e8408-2d22-45f9-82aa-01a7884c0603");
SafeDataReader sd = (SafeDataReader) mocks.DynamicMock(typeof(SafeDataReader));

using (mocks.Record())
{
Expect
.Call(mockDao.ProductGetById(id))
.Return(sd);
}// Replay and validate interaction
ProductDTO p;
using (mocks.Playback())
{
p = r.GetById(id);

}// Post-interaction assertions
Assert.IsNull(p);

}

The first two are not using mock, passed based on the correct data. The last mock test failed, because the somewhere the proxy object stopped me.

System.MissingMethodException: Constructor on type ‘SafeDataReaderProxyf51d8e1fdc964a8d9baa34c2a4592667’ not found.

I am pretty sure DataReader doesn’t have a construtor, so I tried to changed repository to use ISafeDataReader from SafeDataReader, but there is no ISafeDataReader, google says there is a very similar case in subsonic world, but lucky they are using Interface.

Maybe for CSLAEx we have to use TypeMock to “Mock” SafeDataReader.

Wait a minute, here comes Phil Haack’s StubDataReader, the solution is dirty but easy:


         [Test]
        public void GetByIdTestOnRepositoryUsingMockAndStub()
        {
            Guid id = Guid.NewGuid();

            MockRepository mocks = new MockRepository();
            ITrainingDataAccess mockDao = (ITrainingDataAccess)mocks.DynamicMock<ITrainingDataAccess>();

            ProductRepository r = new ProductRepository(mockDao);

            using (mocks.Record())
            {
                //IDataReader dr = (IDataReader) mocks.CreateMock<IDataReader>();
                StubResultSet resultSet
= new StubResultSet("ProductID", "ProductName", "Description", "UnitPrice", "DownloadFile");

                decimal price = 10m;
                resultSet.AddRow(Guid.NewGuid(), "Stub prod", "some desc", price, "1.img");
                IDataReader dr = new StubDataReader(resultSet);

                SafeDataReader sd = new SafeDataReader(dr);

                Expect.Call(mockDao.ProductGetById(id)).Return(sd);

            }// Replay and validate interaction
            ProductDTO p = null;
            using (mocks.Playback())
            {
                p = r.GetById(id);

            }// Post-interaction assertions
            Assert.IsNotNull(p);
            Assert.AreEqual("Stub prod", p.ProductName);
            Assert.AreEqual("some desc", p.Description);
            Assert.AreEqual("1.img", p.DownloadFile);
            Assert.AreEqual(10m, p.UnitPrice);

        }

Update: (2008-07-16)
I used a internal DTO in my BO here which I think is not right, by doing this BO is tightly coupled to DTO. I then changed to mapper class later. Here is a similar idea about using DTO in CSLA from ASP forum.

IOC Container in CSLA

First, we need to create a IocContainer with a static field IWindsorContainer, this idea is from Steven Rockarts. I added a setter to container property, which will make my later unit-test live much easier. The reason is, CSLA does not implement DI (Datacontext or datarepository is hidden in BO base object).

Somewhere in my application’s initialize period, I should do IocContainer init, do does my unit test setup.

IocContainer.Container = new WindsorContainer(new XmlInterpreter(new ConfigResource(“castle”)));

The new CSLA BO’s dataaccess functions look like this:

public static Trainee GetTrainee(int traineeId)
{
return GetTrainee(traineeId, IocContainer.Container.Resolve<ITraineeRepository>());
}

public static Trainee GetTrainee(int traineeId, ITraineeRepository dtx)

In my test, create 2 mock repository classes:

class TraineeRepositoryMock : ITraineeRepository
{
public SerializableEntity<DalLinq.Trainee> GetTrainee(int id)
{
Gain.DalLinq.Trainee t = new Gain.DalLinq.Trainee();
t.Given_Names = “FFFFF”;
SerializableEntity<Gain.DalLinq.Trainee> st = new SerializableEntity<DalLinq.Trainee>(t);
return st;
}

public virtual int SaveTrainee(DalLinq.Trainee obj, DalLinq.Trainee original)
{
Console.WriteLine(“Hi, fake normal update!”);
return 0;
}
}

class TraineeRepositoryMockFalseUpdate : TraineeRepositoryMock
{

override public int SaveTrainee(DalLinq.Trainee obj, DalLinq.Trainee original)
{
Console.WriteLine(“Hi, false update!”);
return -1122;
}
}

The second one is to created to test the update failure exception handling.

The castle config file:

<configSections>
<section name=”castle”
type=”Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor” />
<section name=”cc2″
type=”Castle.Windsor.Configuration.AppDomain.CastleSectionHandler, Castle.Windsor” />
</configSections>

<castle>
<components>
<component id=”traineeRepositoryMock” type=”Gain.Library.Test.TraineeRepositoryMock, Gain.Library.Test”
service=”Gain.DalLinq.ITraineeRepository, Gain.DalLinq” />
</components>
</castle>

<cc2>
<components>
<component id=”traineeRepositoryMockFalseUpdate” type=”Gain.Library.Test.TraineeRepositoryMockFalseUpdate, Gain.Library.Test”
service=”Gain.DalLinq.ITraineeRepository, Gain.DalLinq” />
</components>
</cc2>

The whole unit-test:

[TestFixture]
public class TraineeDATestMock
{

[SetUp]
public void SetUp()
{

IocContainer.Container = new WindsorContainer(new XmlInterpreter(new ConfigResource(“castle”)));

}
[Test]
public void CanGetTraineeTroughMockRepository()
{
Trainee item = Trainee.GetTrainee(2);
Assert.AreEqual(“FFFFF”, item.GivenNames);
}

[Test]
[ExpectedException(typeof(DataPortalException))]
public void CanCatchUpdateTraineeException()
{

// use the new IocContainer to read those false update mock repository.
IocContainer.Container = new WindsorContainer(new XmlInterpreter(new ConfigResource(“cc2”)));

Trainee oldTrainee = Trainee.GetTrainee(2);
oldTrainee.GivenNames = “BBBB”;
oldTrainee.Save();

}

[Test]
public void CanUpdateTrainee()
{

Trainee oldTrainee = Trainee.GetTrainee(2);

oldTrainee.GivenNames = “AAAA”;
Trainee newTrainee = oldTrainee.Save();
Assert.AreEqual(“AAAA”, newTrainee.GivenNames);

}
}

I think this way of unit-test CSLA BO is clearer than TypeMock. We should try to avoid to use TypeMock, unless you are testing a legacy app, as Billy McCaffery pointed out:

a tool such as TypeMock should be used only when absolutely necessary as it can lead to habits of not programming-to-interface.

In fact, those ‘Mock’ objects I created should be called stub. A stub is a class that is hard-coded to return data from its methods and properties. Thanks to Jeremy Miller for clarification.

My question is, becuase TypeMock doesn’t work with castle windsor container, can I use Rhino Mock to mock this internal/private Repository object instead of using stub + switching different castle config file?

TypeMock LinQ DataContext in CSLA BO

Still not quiet clear how this work, but I finally made it, the basic idea is:

I made CSLA BO which calls LinQ DataContext to do the retrieve and update. The main purpose for this is to encapsulate LinQ synatx from CSLA coding.

To test CSLA BO without database, mock LinQ DataContext is necessary. So TypeMock is here, even I add IDataConext into CSLA BO, I found I can not pass this IDataconext as a constructor parameter to it. Fortunately, TypeMock can do kind of ‘internal object injection’ to mock the database!

[Test]
[VerifyMocks]
public void CanGetTraineeName()
{
Gain.DalLinq.Trainee t = new Gain.DalLinq.Trainee();
t.Given_Names = “Frank”;
SerializableEntity<Gain.DalLinq.Trainee> st = new SerializableEntity<DalLinq.Trainee>(t);

// This is the key to mock the future dataconext object.
Mock mocky = MockManager.Mock(typeof(TrainingDataContext));

using (RecordExpectations r = RecorderManager.StartRecording())
{
ITrainingDataContext mockedDbx = new TrainingDataContext();

// Mock GetTrainee method. parameter doesn’t matter.
SerializableEntity<Gain.DalLinq.Trainee> mocked = mockedDbx.GetTrainee(2);

r.Return(st);
}

Trainee item = Trainee.GetTrainee(2);
Assert.AreEqual(“Frank”, item.GivenNames);

[Test]
[VerifyMocks]
[ExpectedException(typeof(DataPortalException))]
public void CanCatchUpdateTraineeException()
{

Gain.DalLinq.Trainee t = new Gain.DalLinq.Trainee();
t.Given_Names = “Frank”;
SerializableEntity<Gain.DalLinq.Trainee> st = new SerializableEntity<DalLinq.Trainee>(t);

Mock mocky = MockManager.Mock(typeof(TrainingDataContext));

using (RecordExpectations r = RecorderManager.StartRecording())
{

ITrainingDataContext dtx = new TrainingDataContext();
SerializableEntity<Gain.DalLinq.Trainee> mocked = dtx.GetTrainee(1);

r.Return(st);

int m = dtx.SaveTrainee(null, null);

r.Return(-1122);
}

Trainee oldTrainee = Trainee.GetTrainee(2);
Assert.AreEqual(“Frank”, oldTrainee.GivenNames);

oldTrainee.GivenNames = “AAAA”;
oldTrainee.Save();

}

[Test]
[VerifyMocks]
public void CanUpdateTrainee()
{

Gain.DalLinq.Trainee t = new Gain.DalLinq.Trainee();
t.Given_Names = “Frank”;
SerializableEntity<Gain.DalLinq.Trainee> st = new SerializableEntity<DalLinq.Trainee>(t);

Mock mockDbx = MockManager.Mock(typeof(TrainingDataContext));

using (RecordExpectations r = RecorderManager.StartRecording())
{

TrainingDataContext dtx = new TrainingDataContext();
SerializableEntity<Gain.DalLinq.Trainee> mocked = dtx.GetTrainee(1);

r.Return(st);

int m = dtx.SaveTrainee(null, null);

r.Return(0);
}

Trainee oldTrainee = Trainee.GetTrainee(2);
Assert.AreEqual(“Frank”, oldTrainee.GivenNames);

oldTrainee.GivenNames = “AAAA”;
Trainee newTrainee = oldTrainee.Save();
Assert.AreEqual(“AAAA”, newTrainee.GivenNames);

}

The idea is from Ben Hall. I add interface in, to focus on testing CSLA only.

Even it’s a great solution to separate dbtest, but I think if we use Windsor Container correctly, those mock tests can be much simpler and clearer, I will post this later.