fake DataRepository - 模拟数据库
快速信息:我正在使用 C# 4.0 和 RhinoMocks(带有 AAA),
我将用一些代码解释我正在考虑做什么:
public class SampleData
{
private List<Person> _persons = new List<Person>()
{
new Person { PersonID = 1, Name = "Jack"},
new Person { PersonID = 2, Name = "John"}
};
public List<Person> Persons
{
get { return _persons; }
}
}
所以这是一个模仿数据库中数据的类。现在我想在单元测试中使用这些数据。换句话说,我不想从数据库中获取数据,而是想从数据存储库中获取数据。
我认为我可以通过存根存储库并使其使用 DataRepository 来实现此目的:
UC1003_ConsultantsBeherenBL consultantsBeherenBL = new UC1003_ConsultantsBeherenBL();
consultantsBeherenBL = MockRepository.GeneratePartialMock<UC1003_ConsultantsBeherenBL>();
consultantsBeherenBL.Repository = MockRepository.GenerateMock<IRepository>();
这将导致我的代码自动在 DataRepository 中查找数据。因此,不是存根方法并直接插入列表(例如 d => d.Find(Arg.Is.Anything)).IgnoreArguments().Return(您刚刚填写的列表)) 我会得到“真实的" 数据返回(已从 DataRepository 中过滤出来的数据)。这意味着我可以测试我的代码是否真的可以找到某些内容,而无需在数据库中插入测试数据(集成测试)。
我将如何实施这样的事情?我尝试在网上查找文章或问题,但我似乎找不到很多:/
任何帮助表示赞赏。
编辑:我尝试过 SimpleInjector 和 StructureMap,但我一直坚持实现其中之一。
我目前在我的实体框架上使用存储库,所以我的 baseBL 看起来像这样(注意:我的所有其他 BL 都继承自这个):
public class BaseBL
{
private IRepository _repository;
public IRepository Repository
{
get
{
if (_repository == null)
_repository = new Repository(new DetacheringenEntities());
return _repository;
}
set { _repository = value; }
}
public IEnumerable<T> GetAll<T>()
{
... --> Generic methods
我的存储库类:
public class Repository : BaseRepository, IRepository
{
#region Base Implementation
private bool _disposed;
public Repository(DetacheringenEntities context)
{
this._context = context;
this._contextReused = true;
}
#endregion
#region IRepository Members
public int Add<T>(T entity)
... --> implementations of generic methods
据我所知,我现在需要能够在我的测试中,我需要使用我的 DataRepository,而不是使用 DetacheringenEntities。我不明白如何用数据类切换实体框架,因为该数据类不适合那里。
我应该让我的 DataRepository 继承我的 IRepository 类并进行自己的实现吗?
public class SampleData : IRepository
但我不能用我的列表做这样的事情:/
public IEnumerable<T> GetAll<T>()
{
return Repository.GetAll<T>();
}
再次非常感谢您的帮助
编辑:我意识到单元测试不需要数据存储库,所以我只是测试该逻辑在集成测试中。这使得数据存储库毫无用处,因为可以在没有存储库的情况下测试代码。 我还是要感谢大家的帮助,谢谢:)
Quick Info: I'm using C# 4.0 and RhinoMocks (with AAA)
I'll explain with some code what I'm thinking about doing:
public class SampleData
{
private List<Person> _persons = new List<Person>()
{
new Person { PersonID = 1, Name = "Jack"},
new Person { PersonID = 2, Name = "John"}
};
public List<Person> Persons
{
get { return _persons; }
}
}
So this is a class which mimics data in the DB. Now I want to use this data in my unit tests. In other words, instead of getting data out of the DB, I want to get them out of the datarepository.
I think I can achieve this by stubbing the Repository and by making it use the DataRepository instead:
UC1003_ConsultantsBeherenBL consultantsBeherenBL = new UC1003_ConsultantsBeherenBL();
consultantsBeherenBL = MockRepository.GeneratePartialMock<UC1003_ConsultantsBeherenBL>();
consultantsBeherenBL.Repository = MockRepository.GenerateMock<IRepository>();
This would cause my code to automaticly look for data in the DataRepository instead. So instead of stubbing a method and directly inserting a list (e.g. d => d.Find(Arg.Is.Anything)).IgnoreArguments().Return(a list which you just filled up)) I'd get "real" data back (the data which has been filtered from the DataRepository). This means I can test if my code can really find something, without having to insert test data in my DB (integration test).
How would I go about implementing such a thing? I've tried looking on the web for articles or questions, but I can't seem to find a lot :/
Any help is appreciated.
EDIT: I've tried to SimpleInjector and StructureMap, but I'm stuck implementing one of them.
I'm currently using a repository on my entity framework, so my baseBL looks like this (note: all my other BL's enherit from this one):
public class BaseBL
{
private IRepository _repository;
public IRepository Repository
{
get
{
if (_repository == null)
_repository = new Repository(new DetacheringenEntities());
return _repository;
}
set { _repository = value; }
}
public IEnumerable<T> GetAll<T>()
{
... --> Generic methods
My Repository class:
public class Repository : BaseRepository, IRepository
{
#region Base Implementation
private bool _disposed;
public Repository(DetacheringenEntities context)
{
this._context = context;
this._contextReused = true;
}
#endregion
#region IRepository Members
public int Add<T>(T entity)
... --> implementations of generic methods
As far as I can make out, I now need to be able to say in my tests that instead of using the DetacheringenEntities, I need to use my DataRepository. I don't understand how I switch out my entity framework with a data class, because that data class won't fit in there.
Should I let my DataRepository enherit my IRepository class and make my own implementations?
public class SampleData : IRepository
But I can't do things like this with my lists :/
public IEnumerable<T> GetAll<T>()
{
return Repository.GetAll<T>();
}
Big thanks again for help
EDIT: I realised that a unit test doesn't need a data repository, so I'm just testing that logic in an integration test. This makes a data repository useless, since the code can be tested without a repository.
I'd like to thank everybody for their help though, thanks :)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
使用依赖注入框架来处理您的依赖项。在单元测试中,您可以将实际实现与存根实现交换。
例如,在 StructureMap 中,您会在代码中说。 “好吧,现在给我
IDataRepository
的活动实例”,对于您的普通代码,这将指向真实数据库的实现。在你的单元测试中,你可以通过放置ObjectFactory.Inject(new FakeDataRepository())
来覆盖它。然后,您的所有代码都会使用该假存储库,这使得测试单个工作单元变得非常容易。ÍUse a Dependency injection framework to handle your dependencies. In your unit test you can swap the real implementation with a stubbed one.
In StructureMap for example, you'll say in your code. "All right, now give me the active instance of
IDataRepository
", for your normal code this would point to an implementation to the real database. In your unittest you can then overwrite this by puttingObjectFactory.Inject(new FakeDataRepository())
. The fake repo is then used by all your code, which makes it really easy to test a single unit of work.Í