Cassini/WebServer.WebDev、NUnit 和 AppDomainUnloadedException
我正在使用 Cassini/WebServer.WebDev 使用 NUnit 运行 WebService 的一些自动化测试。
我没有做任何花哨的事情,只是
public class WebService{
Microsoft.VisualStudio.WebHost.Server _server;
public void Start(){
_server = new Microsoft.VisualStudio.WebHost.Server(_port, "/", _physicalPath);
}
public void Dispose()
{
if (_server != null)
{
_server.Stop();
_server = null;
}
}
}
[TestFixture]
public void TestFixture{
[Test]
public void Test(){
using(WebService webService = new WebService()){
webService.Start();
// actual test invoking the webservice
}
}
}
,但是当我使用 nunit-console.exe 运行它时,我得到以下输出:
NUnit version 2.5.0.9015 (Beta-2)
Copyright (C) 2002-2008 Charlie Poole.\r\nCopyright (C) 2002-2004 James W. Newki
rk, Michael C. Two, Alexei A. Vorontsov.\r\nCopyright (C) 2000-2002 Philip Craig
.\r\nAll Rights Reserved.
Runtime Environment -
OS Version: Microsoft Windows NT 6.0.6001 Service Pack 1
CLR Version: 2.0.50727.1434 ( Net 2.0.50727.1434 )
ProcessModel: Default DomainUsage: Default
Execution Runtime: net-2.0.50727.1434
.....
Tests run: 5, Errors: 0, Failures: 0, Inconclusive: 0 Time: 28,4538451 seconds
Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0
Unhandled exceptions:
1) TestCase1 : System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
2) TestCase2 : System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
3) TestCase3 : System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
4) TestCase4 : System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
如果我在调试器下运行 nunit-console,我会在调试控制台中得到以下输出:
[...]
The thread 0x1974 has exited with code 0 (0x0).
############################################################################
############## S U C C E S S #################
############################################################################
Executed tests : 5
Ignored tests : 0
Failed tests : 0
Unhandled exceptions : 4
Total time : 25,7092944 seconds
############################################################################
The thread 0x1bd4 has exited with code 0 (0x0).
The thread 0x10f8 has exited with code 0 (0x0).
The thread '<No Name>' (0x1a80) has exited with code 0 (0x0).
A first chance exception of type 'System.AppDomainUnloadedException' occurred in System.Web.dll
##### Unhandled Exception while running
System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
at System.Web.Hosting.ApplicationManager.HostingEnvironmentShutdownComplete(String appId, IApplicationHost appHost)
at System.Web.Hosting.HostingEnvironment.OnAppDomainUnload(Object unusedObject, EventArgs unusedEventArgs)
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in System.Web.dll
The thread 0x111c has exited with code 0 (0x0).
The program '[0x1A64] nunit-console.exe: Managed' has exited with code -100 (0xffffff9c).
有人有吗有什么想法可能会导致这种情况吗?
I am using Cassini/WebServer.WebDev to run some automated tests of a WebService using NUnit.
I am not doing anything fancy, just
public class WebService{
Microsoft.VisualStudio.WebHost.Server _server;
public void Start(){
_server = new Microsoft.VisualStudio.WebHost.Server(_port, "/", _physicalPath);
}
public void Dispose()
{
if (_server != null)
{
_server.Stop();
_server = null;
}
}
}
[TestFixture]
public void TestFixture{
[Test]
public void Test(){
using(WebService webService = new WebService()){
webService.Start();
// actual test invoking the webservice
}
}
}
, but when I run it using nunit-console.exe, I get the following output:
NUnit version 2.5.0.9015 (Beta-2)
Copyright (C) 2002-2008 Charlie Poole.\r\nCopyright (C) 2002-2004 James W. Newki
rk, Michael C. Two, Alexei A. Vorontsov.\r\nCopyright (C) 2000-2002 Philip Craig
.\r\nAll Rights Reserved.
Runtime Environment -
OS Version: Microsoft Windows NT 6.0.6001 Service Pack 1
CLR Version: 2.0.50727.1434 ( Net 2.0.50727.1434 )
ProcessModel: Default DomainUsage: Default
Execution Runtime: net-2.0.50727.1434
.....
Tests run: 5, Errors: 0, Failures: 0, Inconclusive: 0 Time: 28,4538451 seconds
Not run: 0, Invalid: 0, Ignored: 0, Skipped: 0
Unhandled exceptions:
1) TestCase1 : System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
2) TestCase2 : System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
3) TestCase3 : System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
4) TestCase4 : System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
If I run nunit-console under the debugger, I get the following output in the debug console:
[...]
The thread 0x1974 has exited with code 0 (0x0).
############################################################################
############## S U C C E S S #################
############################################################################
Executed tests : 5
Ignored tests : 0
Failed tests : 0
Unhandled exceptions : 4
Total time : 25,7092944 seconds
############################################################################
The thread 0x1bd4 has exited with code 0 (0x0).
The thread 0x10f8 has exited with code 0 (0x0).
The thread '<No Name>' (0x1a80) has exited with code 0 (0x0).
A first chance exception of type 'System.AppDomainUnloadedException' occurred in System.Web.dll
##### Unhandled Exception while running
System.AppDomainUnloadedException: Attempted to access an unloaded AppDomain.
at System.Web.Hosting.ApplicationManager.HostingEnvironmentShutdownComplete(String appId, IApplicationHost appHost)
at System.Web.Hosting.HostingEnvironment.OnAppDomainUnload(Object unusedObject, EventArgs unusedEventArgs)
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in mscorlib.dll
A first chance exception of type 'System.Threading.ThreadAbortException' occurred in System.Web.dll
The thread 0x111c has exited with code 0 (0x0).
The program '[0x1A64] nunit-console.exe: Managed' has exited with code -100 (0xffffff9c).
Do anyone have any ideas what could be causing this?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我有同样的问题,但没有使用卡西尼号。 相反,我拥有自己的基于 System.Net.HttpListener 的 Web 服务器托管,通过
System.Web.HttpRuntime
运行在通过System.Web.HttpRuntime
创建的不同应用程序域中,并通过 ASP.Net 支持。代码>System.Web.Hosting.ApplicationHost.CreateApplicationHost()。 这本质上就是 Cassini 的工作方式,只不过 Cassini 在套接字层工作并实现了 System.Net.HttpListener 本身提供的许多功能。不管怎样,为了解决我的问题,我需要在让 NUnit 卸载我的应用程序域之前调用 System.Web.HttpRuntime.Close()。 我通过在主机代理类中公开一个新的
Close()
方法来做到这一点,该方法由我的 [SetupFixture] 类的 [TearDown] 方法调用,并且该方法调用System.Web.HttpRuntime .Close()
。我通过 .Net Reflector 查看了 Cassini 实现,尽管它使用 System.Web.HttpRuntime.ProcessRequest(),但它似乎没有调用 System.Web.HttpRuntime.Close( ) 任何地方。
我不太确定如何继续使用预构建的 Cassini 实现 (
Microsoft.VisualStudio.WebHost.Server
),因为您需要获取System.Web.HttpRuntime.Close ()
调用发生在 Cassini 创建的用于托管 ASP.Net 的应用程序域内。作为参考,这里是我使用嵌入式网络托管进行的工作单元测试的一些部分。
我的
WebServerHost
类是一个非常小的类,它允许将请求编组到由System.Web.Hosting.ApplicationHost.CreateApplicationHost()
创建的应用程序域中。WebServerContext
类只是一个System.Net.HttpListenerContext
实例的包装器,该实例派生自 System.MarshalByRefObject,以允许来自新 ASP.Net 托管域的调用回调到我的域名。WebServerRequest
类只是抽象System.Web.HttpWorkerRequest
类的实现,它通过WebServerContext< 从 ASP.Net 托管域回调到我的域/代码> 类。
WebServer
类是用于启动和停止 Web 服务器的控制器。 启动后,将使用我的WebServerHost
类创建 ASP.Net 托管域作为代理以允许交互。 System.Net.HttpListener 实例也会启动,并启动一个单独的线程来接受连接。 建立连接后,线程池中会启动一个工作线程来处理请求,同样是通过我的WebServerHost
类。 最后,当Web服务器停止时,监听器也停止,控制器等待接受连接的线程退出,然后关闭监听器。 最后,HTTP 运行时也通过调用WebServerHost.Close()
方法关闭。最后,这个
Initialization
类标记为NUnit [SetupFixture] 属性,用于在单元测试开始时启动 Web 服务器,并在单元测试完成时关闭它。我知道这并不能完全回答问题,但我希望这些信息对您有用。
I had the same problem, but was not using Cassini. Instead, I had my own web server hosting based on
System.Net.HttpListener
with ASP.Net support throughSystem.Web.HttpRuntime
running in a different application domain created viaSystem.Web.Hosting.ApplicationHost.CreateApplicationHost()
. This is essentially the way Cassini works, except that Cassini works at the socket layer and implements a lot of the functionality provided bySystem.Net.HttpListener
itself.Anyway, to solve my problem, I needed to call
System.Web.HttpRuntime.Close()
before letting NUnit unload my application domain. I did this by exposing a newClose()
method in my host proxy class that is invoked by the [TearDown] method of my [SetupFixture] class and that method callsSystem.Web.HttpRuntime.Close()
.I looked at the Cassini implementation through .Net Reflector and, although it uses
System.Web.HttpRuntime.ProcessRequest()
, it doesn't seem to callSystem.Web.HttpRuntime.Close()
anywhere.I'm not exactly sure how you can keep using the pre-built Cassini implementation (
Microsoft.VisualStudio.WebHost.Server
), as you need to get theSystem.Web.HttpRuntime.Close()
call to occur within the application domain created by Cassini to host ASP.Net.For reference, here are some pieces of my working unit test with embedded web hosting.
My
WebServerHost
class is a very small class that allows marshaling requests into the application domain created bySystem.Web.Hosting.ApplicationHost.CreateApplicationHost()
.The
WebServerContext
class is simply a wrapper around aSystem.Net.HttpListenerContext
instance that derives from System.MarshalByRefObject to allow calls from the new ASP.Net hosting domain to call back into my domain.The
WebServerRequest
class is just an implementation of the abstractSystem.Web.HttpWorkerRequest
class that calls back into my domain from the ASP.Net hosting domain via theWebServerContext
class.The
WebServer
class is a controller for starting and stopping the web server. When started, the ASP.Net hosting domain is created with myWebServerHost
class as a proxy to allow interaction. ASystem.Net.HttpListener
instance is also started and a separate thread is started to accept connections. When connections are made, a worker thread is started in the thread pool to handle the request, again via myWebServerHost
class. Finally, when the web server is stopped, the listener is stopped, the controller waits for the thread accepting connections to exit, and then the listener is closed. Finally, the HTTP runtime is also closed via a call into theWebServerHost.Close()
method.Finally, this
Initialization
class, marked with the NUnit [SetupFixture] attribute, is used to start the web server when the unit tests are started, and shut it down when they are completed.I know that this is not exactly answering the question, but I hope you find the information useful.