Wade I'm in the same situation. I returned from an agile training course and I am now working through daily examlpes of BDD/TDD/Agile (i'll call it agile from here on out) and LLBL.
since your using VS2008 and ajax you may want to consider using the MS MVC framwork which will be previewed in a few weeks.
Separate Business Layer or direct LLBLGen generated code? I debate this one too. Should LLBL just be a DAL, or should the entities be my Domain objects? for my current project they are my domain objects. I am finding that mocking (RhinoMocks) entity classes works, but i would prefer mocking entity interfaces (ICustomerEntity).
One methodology i did pickup at my training was to use presentation dtos and completely shield the presenation from the domain via a service/task layer. this requires more code and complexity, but allows you to develop the gui/presentation independent of the domain/bll.
my personal preference is adapter. this also helps with unit testing. mockery.DyanmicMock<IDataAccessAdapter>(). I can now test the behavior of a repository without actually accessing a physical database. not sure if that possible with SS.
The current delima i have is truely testing a repository object. example
public class CustomerRepository : ICustomerRepository
{
public CustomerRepository()
: this(new DataAccessAdapter())
{
}
public CustomerRepository(IDataAccessAdapter adapter)
{
this.adapter = adapter;
}
public EntityCollection<CustomerEntity> FetchAllCustomersIn(string state)
{
EntityCollection<CustomerEntity> listOfCustomers = new EntityCollection<CustomerEntity>();
IRelationPredicateBucket bucket = new RelationPredicateBucket(CustomerFields.State == state);
adapter.FetchEntityCollection(listOfCustomers, bucket);
return listOfCustomers;
}
}
if i want to unit test this it looks like this:
[TestFixture]
public class CustomerRepositoryTest
{
MockyRepository mockery;
private IDataAccessAdapter mockAdapter;
[SetUp]
public void Setup()
{
mockery = new MockRepository();
mockAdapter = mockery.DynamicMock<IDataAccessAdapter>();
}
[Test]
public void Should_be_able_to_fetch_all_customers_located_in_PA()
{
string pa = "PA";
using (mockery.Record())
{
mockAdapter.FetchEntityCollection(new EntityCollection<CustomerEntity>(), new RelationPredicateBucket(CustomerFields.State == pa));
LastCall.IgnoreArguments();
}
using (mockery.Playback())
{
CreateSUT().FetchAllCustomersIn(pa);
}
}
private ICustomerRepository CreateSUT()
{
return new CustomerRepository(mockAdapter);
}
}
this works and passes. only because i ignore the arguments passed to the mockAdapter. If i remove LastCall.IgnoreArguments(); then the test will fail because the agruements passed to the mockAdapter are not the actual objects used by CustomerRepository. I could as easily passed null as the agruements. with this test i truely testing behavoir, not state. I would need an integration test to truely access the db and fetch all the customers in pa.
i haven't found a better way to handel this scenario yet. One thought would be to have a factory class return IRelationPredicateBucket. then i could mock the call to create the bucket. This would require quite a few factories through sorts, groupings, prefetches, collections.
as for testing web based gui. you could use Watin [http://watin.sourceforge.net/]. i haven't used this, but I have heard it mentioned before.
this is where I am now with agile testing.