问题
My code basically looks like this:
Data access contract:
public interface IProvideDataAccess<T>
where T : Entity
{
IEnumerable<T> Select(Func<T, bool> condition);
void Save(T entity);
void Delete(T entity);
}
Data access layer:
public class Db4oProvider<T> : IProvideDataAccess<T>
where T : Entity
{
private IEmbeddedConfiguration _configuration;
private string _connectionString;
public Db4oAccesDonnees(string connectionString)
{
_connectionString = connectionString;
_configuration = Db4oEmbedded.NewConfiguration();
}
IEnumerable<T> IProvideDataAccess<T>.Select(Func<T, bool> condition)
{
using (IObjectContainer db = Db4oEmbedded.OpenFile(_configuration, _connexion))
{
return db.Query<T>(e => condition(e));
}
}
void IProvideDataAccess<T>.Save(T entity)
{
using (IObjectContainer db = Db4oEmbedded.OpenFile(_configuration, _connexion))
{
db.Store(entity);
}
}
void IProvideDataAccess<T>.Delete(T entity)
{
using (IObjectContainer db = Db4oEmbedded.OpenFile(_configuration, _connexion))
{
db.Delete(entity);
}
}
}
Business logic layer:
public class MyRepository
{
protected IProvideDataAccess<MyEntityType> _dataAccessProvider;
public MyRepository(IProvideDataAccess<MyEntityType> dataAccessProvider)
{
_dataAccessProvider = dataAccessProvider;
}
public IEnumerable<MyEntityType> SelectValidEntities()
{
return _dataAccessProvider.Select(e => /* test if entity is valid */);
}
}
Unit/Integration tests are fairly new to me and I'm not sure where to begin.
I think the logical thing to do would be to
- write integration tests for the DAL
- write unit tests for the BLL (with fake DAL)
I this correct?
My biggest problem is with the "select" method and its Func parameter. How do I test/mock that?
Basically, what tests should I write for these two classes?
回答1:
Your DAL
looks like the classes which never change... In my opinion creating a UT
or IT
on them is a waste of time. You should cover class's behavior like Db4oProvider<T>
with a good Component/"large Integration"(not only the unit + DB) tests. I offer you to read about Test Pyramid
(In Martin Fowler blog and this good article). I like the following pyramid:
About the Select
method:
In Integration test
(unit + DB) you have to put data inside your DB(or keep a DB with data...), call Select
with a condition, then verify that you've got the expected data.
In Component test
you need to test it as a part of behavior under test, if the test succeed then every thing is alright...
In UT
the tests are split into 2 types:
1.The tests where you verify the behaviour of the condition(lambda) you pass into Select
method:(in this way you also verify that Select
was called with the right parameters... In my examples I use RhinoMocks
)
var fakeProvider = MockRepository.GenerateStub<IProvideDataAccess<Entity>>();
fakeProvider.Select(o => o.Id =="asdfg");
fakeProvider.AssertWasCalled(access => access.Select(Arg<Func<Entity, bool>>
.Matches(func => func(new Entity()
{
Id = "asdfg"
}))));
2.The tests where you verify caller method behaviour. In those tests you should configure your DAL
to return something matter the parameters are:
_selectResult = new List<Entity>();
fakeProvider.Stub(x => x.Select(Arg<Func<Entity, bool>>.Is.Anything))
.Return(_selectResult);
来源:https://stackoverflow.com/questions/32013575/unit-integration-tests-for-dal-and-bll-with-lambdas