2013-07-31 59 views
1

我使用NHibernate和一个相当大的项目Repository模式,我试图建立我的服务层单元测试策略和时遇到一些问题,让在在我的脑海。我可能错误地接触了单元测试,也可能是我错误地处理了Repository模式,但我不确定哪一个。单元测试策略,NHibernate的库

我的方案的简化子集是这样的:

public class UserRepository : RepositoryBase, IRepository 
{ 

    public UserRepository() {} 
    public UserRepository(ISession sessionParam) { 
     session = sessionParam; // member of repository base 
    } 

    public string GetUsernameFromEmail(string emailAddress) { 
     return session.QueryOver<Members>().List().Where(u => u.EmailAddress.ToLowerInvariant() == emailAdrress.ToLowerInvariant()).FirstOrDefault().Username; 
    } 

} 

我的单元测试的概念是,我会假NHibernate的ISession的,并传递一个返回的用户列表,将适合的场景我”我试图测试(例如,电子邮件地址是不区分大小写的)(我也无法让它与FakeItEasy一起工作,但这是另一个问题,我是否应该沿着这条路走下去)。请记住,我们不应该伪造我们不拥有的对象,我可以看到不想伪造ISession的逻辑,并且我一直在阅读很多关于如何不测试存储库的内容 - 这也太远远低于单元测试。

但是,即使在有中,我想单元测试库逻辑这个非常基本的情况。其他存储库方法可能会有更多的逻辑(例如数据验证等)。我知道我可以使用SqlLite或类似的东西为reporitory构建相对快速的集成测试,但在我看来,这个逻辑应该是单元测试的。

在库依托有多数民众赞成由一个Asp.Net MVC4现场消耗的(WCF)服务层。

在最好的世界中,我会在WCF层构建我的单元测试,并伪造IRepository进行测试,但我没有看到如何在不让所有用户将此逻辑移动到服务层的情况下从存储库中返回到服务层,这看起来很荒谬。

所以我的问题是:什么一块整体架构这里我有我的头从根本上错了吗?

编辑

在回应@ Wiktor的-zychla的答案,这是我关于我为什么要假的Isession逻辑。在考虑这个特定的测试时,我希望我的存储库使用ISession的实现,它总是返回一个具有混合大小写的电子邮件地址和特定用户名的用户,传递所有小写的电子邮件地址,并返回值是我指示我的假使用的用户名。那样,我正在测试我的逻辑是否有一个知道的值 - 无论NHibernate是否会在真实世界中运行,这不是我关心的问题 - 测试存储库方法中的逻辑是。再次,我知道这是一个微不足道,天真的例子,可以通过许多其他方式解决 - 它只是站在更复杂的功能上,我希望以后能够测试。

回答

2

我不认为你应该试图伪造ISession。这没有多大意义 - NHibernate存储库是一个抽象概念的具体实现,你想要测试的是这个具体实现是否可以,而不是进一步抽象并测试什么?一个不同的假linq实现,然后假装NH遵循它?在测试开始之前,让你注入一个临时的Isession到存储库,但仍的Isession指向一个真实的数据库

单元测试应该涉及到一个真正的数据库的话,很可能成立。

另一方面,当您测试使用存储库的服务时,将另一个存储库实现注入到服务层中是完全有效的。

+0

感谢您的评论@Wiktor。我担心的是,一旦我介绍一个实际的数据库,我们不再谈论单元测试 - 这些都是集成测试,我绝对必须这样做,但这不是我在这里问的。 – cori

+0

没必要。这正是边缘情况之一,你需要考虑是否进一步抽象是有意义的。我对此的看法(我相信会分享给我的大多数人)将会是你无法可靠地伪造一个linq提供者,而这正是单元测试的必要条件。我的答案基本上是“不要单位测试这个你觉得似乎被吸引的东西”。 –

+0

从你的评论我相信你正试图把太多的责任放入库层。非平凡的处理,validatiin等应该在上层完成,从而使其易于测试。想一想 - 你会在同一个存储库接口的两个或多个实现中重复使用相同的验证或处理逻辑吗? –