2009-12-30 79 views
14

在创建单元测试时,有没有办法在ASP.Net Web窗体中模拟/伪造会话对象?如何在ASP.Net Web窗体中模拟/伪造会话对象?

我目前正在将用户详细信息存储在由我的业务逻辑访问的会话变量中。

当单独测试我的业务逻辑时,会话不可用。这似乎表明设计不好(虽然我不确定)。业务逻辑层应该首先访问会话变量吗?

如果是这样,那么我将如何去交换用户测试的虚假对象的细节?

+0

也看到我对这个问题的答案 - http://stackoverflow.com/a/8487847/232593 – 2011-12-14 10:48:39

回答

9

在ASP.NET中,您无法创建HttpSessionState的测试双因为它是sealed。是的,这对于ASP.NET的原始设计师来说是不好的设计,但对此没有太多要做。

这是TDD和其他固体实践者基本上放弃ASP.NET而转向ASP.NET MVC和其他更可测试的框架的原因之一。在ASP.NET MVC中,HTTP会话由抽象的HttpSessionStateBase类建模。

您可以采取类似的方法,让对象在抽象会话上工作,然后在ASP.NET环境中运行时包装真正的HttpSessionState类。根据具体情况,您甚至可以重用System.Web.Abstractions中的类型,但如果不是,您可以定义自己的类型。

在任何情况下,您的业务逻辑是您的业务逻辑是域模型它应该独立于任何特定的运行时技术建模,所以我会说它不应该首先访问会话对象。

如果你绝对需要使用测试双打涉及HttpSessionState单元毒鼠强,这依旧可能带有一定侵入性的动态模拟考试,如TypeMockMoles,althought这些携带大量的缺点,以及(见this comparison of dynamic mocks)。

1

你的直觉是正确的---你不应该从你的业务逻辑访问ASP.NET框架的部分。这将包括会话。

要回答你的第一个问题,你可以使用像Typemock隔离器的产品,但如果你在一个界面重构代码换到会话访问,你会更好模拟静态类(即IHttpSession。)然后你可以模拟IHttpSession。

0

一种方法是将lambda表达式传递给代码,该代码将字符串(或其他对象)作为输入,并使用它来设置Session对象或测试容器。

但是,正如其他人所说,将访问Session对象移出BLL是个好主意。

1

在Asp.Net webforms中,你不能逃避框架进入你的代码来自aspx页面的事实。我同意你的业务层不应直接触及asp.net特定的组件,但你必须有一个模型的存储容器,并且在asp.net中的会话是一个很好的领域。因此,一种可能的方法是创建ISessionManager用于在业务层内进行交互。然后,通过使用HttpSessionState实现具体类型...顺便说一句,一个好的技巧是使用HttpContext.Current.Session来实现访问器/ getters从HttpSessionState。 您的下一个挑战将是如何将它们连接在一起。

25

你可以用4行代码来完成。虽然这并不涉及将业务逻辑层移出会话的先前评论,但如果您使用与会话密切相关的遗留代码(我的场景),则有时您可能需要执行此操作。

的命名空间:

using System.Web; 
using System.IO; 
using System.Web.Hosting; 
using System.Web.SessionState; 

代码:

HttpWorkerRequest _wr = new SimpleWorkerRequest(
    "/dummyWorkerRequest", @"c:\inetpub\wwwroot\dummy", 
    "default.aspx", null, new StringWriter()); 

HttpContext.Current = new HttpContext(_wr); 

var sessionContainer = new HttpSessionStateContainer(
    "id", new SessionStateItemCollection(), 
    new HttpStaticObjectsCollection(), 10, true, 
    HttpCookieMode.AutoDetect, SessionStateMode.InProc, false); 

SessionStateUtility.AddHttpSessionStateToContext(
    HttpContext.Current, sessionContainer); 

然后,您可以参考会话没有得到一个NullReferenceException错误:

HttpContext.Current.Session.Add("mySessionKey", 1); 

这是一个代码组合我从下面的文章编译:

+0

优秀的,谢谢。 – 2012-03-21 16:30:55

+0

谢谢,良好的工作 – Manish 2015-02-04 14:01:30

+0

从单元测试类调用索引方法时,我得到ViewEngine异常。有相同的解决方案吗? – Manish 2015-02-04 14:02:47