1

我在一个相当大的项目中使用 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 或类似的东西来为存储库构建相对快速的集成测试,但在我看来,这个逻辑仍然应该进行单元测试。

依赖于存储库,有一个 (WCF) 服务层正在被 Asp.Net MVC4 站点使用。

在最好的情况下,我会在 WCF 层构建我的单元测试并伪造 IRepository 进行测试,但我不知道如何在不从存储库中获取所有用户的情况下将此逻辑移动到服务层和将它们返回到服务层,这似乎很荒谬。

所以我的问题是:这里的整体架构的哪一部分在我的脑海中有根本性的错误?

编辑

为了回应@Wiktor-zychla 的回答,这是我关于为什么要伪造 ISession 的逻辑。在考虑这个特定的测试时,我想让我的存储库使用 ISession 的实现,它总是返回具有混合大小写的电子邮件地址和特定用户名的单个用户,传入一个全小写的电子邮件地址,并返回值是我指示我的假冒使用的用户名。这样我就可以根据已知值测试我的逻辑 - NHibernate 在现实世界中是否会这样运行不是我关心的问题 - 测试存储库方法中的逻辑是。再说一次,我知道这是一个简单而幼稚的例子,可以通过许多其他方式解决——它只是代表我希望以后能够测试的更复杂的功能。

4

1 回答 1

2

我认为您不应该尝试伪造 ISession。这没有多大意义 - NHibernate 存储库是一个抽象概念的具体实现,您要测试的是这个具体实现是否可以,而不是进一步抽象它并测试什么?一个不同的假 linq 实现,然后假装 NH 遵循它?

然后,您的单元测试应该涉及一个真实的数据库,可能在测试开始之前设置,以便您将临时 ISession 注入存储库,但 ISession 仍然指向真实数据库。

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

于 2013-07-31T17:48:51.960 回答