gpt4 book ai didi

.net - Cassini/WebServer.WebDev,NUnit和AppDomainUnloadedException

转载 作者:行者123 更新时间:2023-12-04 04:14:22 29 4
gpt4 key购买 nike

我正在使用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).

有人有什么想法会导致这种情况吗?

最佳答案

我有同样的问题,但是没有使用卡西尼号。取而代之的是,我有自己的基于System.Net.HttpListener的Web服务器托管,并通过System.Web.HttpRuntime在ASP.Net支持下在System.Web.Hosting.ApplicationHost.CreateApplicationHost()创建的不同应用程序域中运行,并具有ASP.Net支持。这基本上是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。

作为引用,这是我的带有嵌入式Web托管的工作单元测试的一些内容。

我的WebServerHost类是一个很小的类,它允许将请求编码到System.Web.Hosting.ApplicationHost.CreateApplicationHost()创建的应用程序域中。

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

public class WebServerHost :
MarshalByRefObject
{
public void
Close()
{
HttpRuntime.Close();
}

public void
ProcessRequest(WebServerContext context)
{
HttpRuntime.ProcessRequest(new WebServerRequest(context));
}
}
WebServerContext类只是对从System.MarshalByRefObject派生的 System.Net.HttpListenerContext实例的包装,以允许来自新ASP.Net托管域的调用回叫到我的域中。
using System;
using System.Net;

public class WebServerContext :
MarshalByRefObject
{
public
WebServerContext(HttpListenerContext context)
{
this.context = context;
}

// public methods and properties that forward to HttpListenerContext omitted

private HttpListenerContext
context;
}
WebServerRequest类只是抽象 System.Web.HttpWorkerRequest类的实现,该类通过 WebServerContext类从ASP.Net托管域回调回我的域。
using System;
using System.IO;
using System.Web;

class WebServerRequest :
HttpWorkerRequest
{
public
WebServerRequest(WebServerContext context)
{
this.context = context;
}

// implementation of HttpWorkerRequest methods omitted; they all just call
// methods and properties on context

private WebServerContext
context;
}
WebServer类是用于启动和停止Web服务器的 Controller 。启动时,将使用我的 WebServerHost类作为代理来创建ASP.Net托管域,以允许进行交互。还启动了 System.Net.HttpListener实例,并启动了一个单独的线程来接受连接。建立连接后,将再次通过 WebServerHost类在线程池中启动工作线程来处理请求。最终,当Web服务器停止时,监听器停止, Controller 等待接受连接的线程退出,然后关闭监听器。 最后,还可以通过调用WebServerHost.Close()方法来关闭HTTP运行时。
using System;
using System.IO;
using System.Net;
using System.Reflection;
using System.Threading;
using System.Web.Hosting;

class WebServer
{
public static void
Start()
{
lock ( typeof(WebServer) )
{
// do not start more than once
if ( listener != null )
return;

// create web server host in new AppDomain
host =
(WebServerHost)ApplicationHost.CreateApplicationHost
(
typeof(WebServerHost),
"/",
Path.GetTempPath()
);

// start up the HTTP listener
listener = new HttpListener();
listener.Prefixes.Add("http://*:8182/");
listener.Start();

acceptConnectionsThread = new Thread(acceptConnections);
acceptConnectionsThread.Start();
}
}

public static void
Stop()
{
lock ( typeof(WebServer) )
{
if ( listener == null )
return;

// stop listening; will cause HttpListenerException in thread blocked on GetContext()
listener.Stop();

// wait connection acceptance thread to exit
acceptConnectionsThread.Join();
acceptConnectionsThread = null;

// close listener
listener.Close();
listener = null;

// close host
host.Close();
host = null;
}
}

private static WebServerHost
host = null;

private static HttpListener
listener = null;

private static Thread
acceptConnectionsThread;

private static void
acceptConnections(object state)
{
while ( listener.IsListening )
{
try
{
HttpListenerContext context = listener.GetContext();
ThreadPool.QueueUserWorkItem(handleConnection, context);
}
catch ( HttpListenerException e )
{
// this exception is ignored; it will be thrown when web server is stopped and at that time
// listening will be set to false which will end the loop and the thread
}
}
}

private static void
handleConnection(object state)
{
host.ProcessRequest(new WebServerContext((HttpListenerContext)state));
}
}

最后,带有NUnit [SetupFixture]属性标记的 Initialization类用于在单元测试开始时启动Web服务器,并在完成单元测试后将其关闭。
using System;
using NUnit.Framework;

[SetUpFixture]
public class Initialization
{
[SetUp]
public void
Setup()
{
// start the local web server
WebServer.Start();
}

[TearDown]
public void
TearDown()
{
// stop the local web server
WebServer.Stop();
}
}

我知道这并不能完全回答问题,但是希望您能从中找到有用的信息。

关于.net - Cassini/WebServer.WebDev,NUnit和AppDomainUnloadedException,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/561402/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com