2009-02-18 7 views
9

मैं कैसिनी/वेबसेवर का उपयोग कर रहा हूं। वेबडेव एनयूनीट का उपयोग करके वेब सेवा के कुछ स्वचालित परीक्षण चलाने के लिए।कैसिनी/वेबसेवर। वेबडेव, एनयूनीट और ऐपडोमेन अनलोडेड एक्सेप्शन

मैं कुछ भी कल्पना नहीं कर रहा हूँ, बस

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- डीबगर के तहत कंसोल, मुझे डीबग कंसोल में निम्न आउटपुट मिलता है:

[...] 
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). 

क्या किसी के पास कोई विचार है जो बी ई यह कारण है?

+0

क्या आपको कभी इस समस्या का समाधान मिला है? मुझे एक समान समस्या है। –

+0

कोई/अच्छा/समाधान नहीं है, लेकिन मैंने एनएनआईटी-टास्क पर असफलता = "झूठी" सेटिंग को समाप्त कर दिया है और एक अलग टूल्स के साथ एक्सएमएल-आउटपुट पोस्टप्रोसेसिंग किया है, जो अनचाहे AppDomainUnloadedException को अनदेखा करता है। –

+0

मैंने https://bugs.launchpad.net/nunitv2/+bug/423611 पर उचित NUnit बग में समस्या का प्रदर्शन करने वाला एक उदाहरण समाधान अपलोड किया है। यह बहुत अच्छा होगा अगर आप इसे आज़मा सकते हैं और इसकी वैधता को पार कर सकते हैं (और लॉन्चपैड पर अपने निष्कर्ष पोस्ट कर सकते हैं) –

उत्तर

7

मुझे एक ही समस्या थी, लेकिन कैसिनी का उपयोग नहीं कर रहा था। इसके बजाय, के माध्यम से बनाए गए एक अलग एप्लिकेशन डोमेन में चल रहे System.Web.HttpRuntime के माध्यम से ASP.Net समर्थन के साथ System.Net.HttpListener पर आधारित मेरा स्वयं का वेब सर्वर होस्टिंग था। यह अनिवार्य रूप से कैसिनी काम करता है, सिवाय इसके कि कैसिनी सॉकेट परत पर काम करता है और System.Net.HttpListener द्वारा प्रदान की गई कई कार्यक्षमताओं को लागू करता है।

वैसे भी, मेरी समस्या को हल करने के लिए, मुझे NUnit को मेरे एप्लिकेशन डोमेन को अनलोड करने से पहले System.Web.HttpRuntime.Close() पर कॉल करने की आवश्यकता थी। मैंने अपने [सेटअप फिक्स्चर] वर्ग की [टीयरडाउन] विधि द्वारा बुलाए गए मेरे होस्ट प्रॉक्सी क्लास में एक नई Close() विधि को उजागर करके ऐसा किया और यह विधि System.Web.HttpRuntime.Close() पर कॉल करती है।

मैंने नेट रिफ्लेक्टर के माध्यम से कैसिनी कार्यान्वयन को देखा और, हालांकि यह System.Web.HttpRuntime.ProcessRequest() का उपयोग करता है, ऐसा लगता है कि यह कहीं भी System.Web.HttpRuntime.Close() पर कॉल नहीं करता है।

मैं बिल्कुल यकीन है कि कैसे आप, पहले से बने कैसिनी कार्यान्वयन (Microsoft.VisualStudio.WebHost.Server) का उपयोग कर के रूप में आप आवेदन ASP.Net की मेजबानी के लिए कैसिनी द्वारा बनाई गई डोमेन के भीतर होने की System.Web.HttpRuntime.Close() कॉल प्राप्त करने की आवश्यकता रख सकते नहीं हूँ।

संदर्भ के लिए, यहां मेरे वर्किंग यूनिट परीक्षण के कुछ टुकड़े एम्बेडेड वेब होस्टिंग के साथ हैं।

मेरा 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.Net.HttpListenerContext उदाहरण है कि System.MarshalByRefObject से निकला नया 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 वर्ग शुरू करने और वेब सर्वर को रोकने के लिए एक नियंत्रक है। प्रारंभ होने पर, ASP.Net होस्टिंग डोमेन को मेरे WebServerHost कक्षा के साथ इंटरैक्शन की अनुमति देने के लिए प्रॉक्सी के रूप में बनाया गया है। एक System.Net.HttpListener उदाहरण भी शुरू किया गया है और कनेक्शन स्वीकार करने के लिए एक अलग धागा शुरू किया गया है।जब कनेक्शन बनाए जाते हैं, तो अनुरोध को संभालने के लिए थ्रेड पूल में एक वर्कर थ्रेड शुरू होता है, फिर से मेरे WebServerHost कक्षा के माध्यम से। अंत में, जब वेब सर्वर बंद हो जाता है, श्रोता बंद कर दिया जाता है, नियंत्रक बाहर निकलने के लिए कनेक्शन स्वीकार करने वाले थ्रेड के लिए प्रतीक्षा करता है, और फिर श्रोता बंद हो जाता है। अंत में, HTTP रनटाइम को WebServerHost.Close() विधि में कॉल के माध्यम से भी बंद कर दिया जाता है।

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)); 
    } 
} 

अंत में, इस Initialization वर्ग, NUnit [SetupFixture] विशेषता के साथ चिह्नित, वेब सर्वर शुरू जब इकाई परीक्षण शुरू कर दिया जाता है, और उसे बंद जब वे पूरा कर रहे हैं करने के लिए प्रयोग किया जाता है।

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(); 
    } 
} 

मुझे पता है कि यह वास्तव में सवाल का जवाब नहीं दे रहा है, लेकिन मुझे आशा है कि आपको जानकारी उपयोगी होगी।

+0

मुझे आश्चर्य है, एक विशेष परीक्षण कैसा दिखता है? क्या उसके शरीर को किसी भी प्रकार की निष्पादन कॉल में लपेटा जाएगा, जिससे बनाए गए ऐपडोमेन को वास्तविक निष्पादन का प्रतिनिधि बनाया जा सके? –

संबंधित मुद्दे