2009-08-10 64 views
2

我们正在建立一个ASP.NET MVC的网站,我与这里定义的连接最好使单元测试挣扎(我使用“连接”一般 - 它可能是一个会话,连接,适配器,或任何其他类型的数据上下文可以管理事务和数据库操作)。在MVC中实例化Data Context(适配器,连接,会话等)的位置?

比方说,我们有3类:

UserController 
UserService 
UserRepository 

在过去,我们会做UserService的方法中是这样的:

Using (ISomeSession session = new SomeSession()) 
{ 
    session.StartTransaction(); 
    IUserRepository rep = new UserRepository(session); 
    rep.DoSomething(); 
    rep.Save(); 
    session.Commit(); 
} 

然而,这是不是真的因为SomeSession的依赖没有被注入,所以可以对它进行单元测试。但是,如果我们使用D.I.要在UserService中注入依赖关系,会话在UserService的整个生命周期中都会挂起。如果从UserController调用了多个服务,则每个会话都可以挂起,直到UserController被垃圾收集为止。

有关如何更好地管理此问题的任何想法?我错过了明显的东西吗?

编辑

对不起,如果我不清楚 - 我知道我可以使用依赖注入与Session /数据上下文,但后来它被保存在服务类的生活。对于任何运行时间较长的操作/方法(即假设服务正在被批处理进程调用),除了增加可测试性之外,这可能会导致大量的开放会话。

+1

如果您使用真正的连接进行测试,那么您不是单元测试,而是集成测试。 – RichardOD 2009-08-10 10:04:34

+0

理查德 - 我明白这一点。我的观点是,我不知道如何在整个课程生命周期中保持连接不活动(或至少上下文活动),而不是在Using语句中的一小段时间内将依赖关系移动到课程级别。 “使用”块似乎更安全,因为它在需要时打开连接,并在完成时关闭连接。 – 2009-08-10 18:37:53

回答

2

由于RichardOD正确指出,你不能使用编写单元测试活动数据库连接。如果你正在做,那么你就是集成测试。

我有我的仓库接口,一个真正的资源库,并进行单元测试一个假仓库单独实现。假存储库在通用列表上工作,而不是真正的数据上下文。我正在使用DI(与Ninject一起使事情变得更加舒适,但您也可以手动完成)来注入正确的存储库。

只有在我与现实的连接单元测试极少数情况下,但是这是我的仓库类单元测试,不为任何控制器,UI或业务层对象。

编辑:随着你添加的评论,我想我现在明白你实际要求的是什么。有趣的是,你会问这个问题,因为我上周工作在同一个主题上:-)

我在非常薄的包装器中实例化数据上下文,并将上下文放在HttpContext.Current.Items字典中。这样,上下文就是全局的,但只适用于当前的请求。

不过,你的问题的主题是很大的误导性。你问“在哪里实例化数据上下文进行单元测试”,答案是你通常不会。我的单元测试仍然使用假存储库。

+0

没关系,如果你downvote,但它会很好解释为什么这种情况... – 2009-08-10 14:31:41

+0

对不起......我应该回应。你的回答是正确的,但我低估了它,因为它没有回答我的问题。我明白D.I.以及如何创建一个虚假的存储库。问题在于上下文是在仓库之外定义的,并且也可以传递给其他服务/仓库类(即他们可以参与交易)。如果我们在Service的c-tor中实例化上下文/连接(或者注入它),上下文的生活将与Service的...一样,实质上,我们将连接状态扩展到远远超出典型的“使用(新上下文) {...}“。 – 2009-08-10 18:08:01

+0

啊,好的。看到我上面的编辑... – 2009-08-10 20:23:03

-2

最简单的方法是让你在web.config中定义的开发和生产的ConnectionString。对于Unittests,你可以在你的Testproject的app.config中定义它。