基于ServiceStack JsonServiceClient的测试失败,但服务在浏览器中工作

时间:2013-05-29 16:36:38

标签: web-services nunit servicestack

在我的单页Web应用程序运行(使用ServiceStack的RazorFormat()MVC提供的网页,而不是.ASP MVC)后,我运行了(以前通过)测试服务。测试失败了。再次测试了Web应用程序(调试运行,导航到浏览器中的//localhost:1337/ResourceList:仍在工作。我的测试有问题吗?

以下是错误:

Test Name:  TestResourceList
Test FullName:  [0-1015]ServiceWrapper.Test.TestSWrapperServices.TestResourceList
Test Source:    c:\Users\uname\Documents\Visual Studio 2012\Projects\ServiceWrapper\UnitTestProject1\ServiceTests.cs : line 96
Test Outcome:   Failed
Test Duration:  0:00:02.188

Result Message: 
System.Net.WebException : Unable to connect to the remote server
  ----> System.Net.Sockets.SocketException : No connection could be made because the target machine actively refused it 127.0.0.1:1337
Result StackTrace:  
at System.Net.HttpWebRequest.GetResponse()
at ServiceStack.ServiceClient.Web.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)
at ServiceStack.ServiceClient.Web.ServiceClientBase.Get[TResponse](IReturn`1 request)
at ServiceWrapper.Test.TestSWrapperServices.TestResourceList() in c:\Users\uname\Documents\Visual Studio 2012\Projects\ServiceWrapper\UnitTestProject1\ServiceTests.cs:line 98
--SocketException
at System.Net.Sockets.Socket.DoConnect(EndPoint endPointSnapshot, SocketAddress socketAddress)
at System.Net.ServicePoint.ConnectSocketInternal(Boolean connectFailure, Socket s4, Socket s6, Socket& socket, IPAddress& address, ConnectSocketState state, IAsyncResult asyncResult, Exception& exception)

以下是测试:

namespace ServiceWrapper.Test
{
    [TestFixture]
    public class TestSWrapperServices
    {
        AppHost appHost;
        private const string ListeningOn = "http://*:1337/";
        public const string Host = "http://localhost:1337";
        private const string BaseUri = Host + "/";

        [TestFixtureSetUp]
        public void OnTestFixtureSetUp()
        {
            var appSettings = new AppSettings();
            var username = Environment.GetEnvironmentVariable("USERNAME");
            var userdomain = Environment.GetEnvironmentVariable("USERDOMAIN");

            AppHost.AppConfig = new AppConfig(new AppSettings());

            appHost = new AppHost();

            // initialize Service Server
            ServiceServer.SetUser(AppHost.AppConfig.UserName, AppHost.AppConfig.Password);
            ServiceServer.SetLog(String.Empty);

            try
            {
                appHost.Init();
                appHost.Start(ListeningOn);
            }
            catch (HttpListenerException ex)
            {
                if (ex.ErrorCode == 5)
                {
                    System.Diagnostics.Debug.WriteLine("You need to run the following command (as admin):");
                    System.Diagnostics.Debug.WriteLine("  netsh http add urlacl url={0} user={1}\\{2} listen=yes",
                        ListeningOn, userdomain, username);
                }
                else
                {
                    System.Diagnostics.Debug.WriteLine("ERROR: {0}: {1}", ex.GetType().Name, ex.Message);
                }
            }
            catch (Exception ex)
            {
                System.Diagnostics.Debug.WriteLine("ERROR: {0}: {1}", ex.GetType().Name, ex.Message);
            }
        }

        [TestFixtureTearDown]
        public void OnTestFixtureTearDown()
        {
            appHost.Dispose();
        }

        [Test]
        public void TestResourceList()
        {
            JsonServiceClient client = new JsonServiceClient(BaseUri);
            ResourceList response = client.Get(new ResourceList());
            Assert.Contains("Some Value", response.property);
        }
        [Test]
    }
}

1 个答案:

答案 0 :(得分:3)

我升级到最新的ServiceStack - 3.9.55,但它仍然无效。所以,我重新开始,从一开始就进行健全检查。事实证明,program.cs ListeningOn有http://*:1337/,而nunit TestFixture ListeningOn是http://localhost:1337/

检查http://localhost:1337/

    C:\Windows\system32>netsh http show urlacl url=http://localhost:1337/

    URL Reservations:
    -----------------

检查http://*:1337/

    C:\Windows\system32>netsh http show urlacl url=http://*:1337/

    URL Reservations:
    -----------------

        Reserved URL            : http://*:1337/
            User: DOMAIN\user
                Listen: Yes
                Delegate: No
                SDDL: D:(A;;GX;;;S-1-5-21-2595267603-2801715271-1705165942-1002)

我之前的故障排除使两个项目的ListeningOn值不一致。有趣的是,使用http:// *:1337 /不能像通配符那样用作通配符网址。

这是一个方便的代码片段,可帮助您构建add urlacl命令。它还对您正在收听的确切网址提供了有用的(!)健全性检查。

    Console.WriteLine("You need to run the following command:");
    Console.WriteLine("  netsh http add urlacl url={0} user={1}\\{2} listen=yes",
    ListeningOn, userdomain, username);

---更新---

升级ServiceStack消除了“连接主动拒绝”错误消息。一旦ListeningOn值统一,真实 错误消息已暴露:

Result Message: ServiceStack.ServiceClient.Web.WebServiceException : Service Unavailable
Result StackTrace:  
at ServiceStack.ServiceClient.Web.ServiceClientBase.ThrowWebServiceException[TResponse](Exception ex, String requestUri)
at ServiceStack.ServiceClient.Web.ServiceClientBase.ThrowResponseTypeException[TResponse](Object request, Exception ex, String requestUri)
at ServiceStack.ServiceClient.Web.ServiceClientBase.HandleResponseException[TResponse](Exception ex, Object request, String requestUri, Func`1 createWebRequest, Func`2 getResponse, TResponse& response)
at ServiceStack.ServiceClient.Web.ServiceClientBase.Send[TResponse](String httpMethod, String relativeOrAbsoluteUrl, Object request)
at ServiceStack.ServiceClient.Web.ServiceClientBase.Get[TResponse](IReturn`1 request)
at RemoteServerWrapper.Test.TestRSWrapperServices.TestDataList() in c:\Users\user\Documents\Visual Studio 2012\Projects\RemoteServerWrapper\UnitTestProject1\ServiceTests.cs:line 183

它仍然模糊不清 - 但至少它没有报道与真实问题完全不同的东西。所以我在app.config中实现了trace,如下所示:

<configuration>

  <!-- ... other config settings ... -->

  <system.diagnostics>
    <sources>
      <source name="System.Net" tracemode="includehex" maxdatasize="1024">
        <listeners>
          <add name="System.Net"/>
          <add name="console"/>
        </listeners>
      </source>
      <source name="System.Net.HttpListener">
        <listeners>
          <add name="System.Net"/>
          <add name="console"/>
        </listeners>
      </source>
    </sources>
    <switches>
      <add name="System.Net" value="Verbose"/>
      <add name="System.Net.HttpListener" value="Verbose"/>
    </switches>
     <sharedListeners>
      <add name="console" 
        type="System.Diagnostics.ConsoleTraceListener" 
        initializeData="false"/>
      <add name="System.Net"
        type="System.Diagnostics.TextWriterTraceListener"
        initializeData="network.log"
      />
    </sharedListeners>
    <trace autoflush="true"/>
  </system.diagnostics>
</configuration>

这暴露了更好的错误消息:

ERROR: [::1]:1337 Request not found: /datarequest?DataKey=some_key&startDate=20130701&endDate=20130708

好的 - 现在我必须引入servicestack源代码,这样我就可以逐步完成代码并弄清楚为什么我在测试中找到'Not Found',当它在我'调试/运行'时运行并通过测试浏览器。事实证明RestHandler.FindMatchingRestPath(httpMethod, pathInfo, contentType)没有返回匹配。姆。这是为什么? AppHost声明相同。那么,有什么不同?

其余服务存在于我项目的主程序中。从'debug / run'运行时,默认程序集具有服务,一切正常。但是当从测试项目运行时,添加了服务程序集作为参考,servicestack无法找到它们。相对于测试项目,它们不在默认位置。所以我在我的测试文件的顶部添加了一个AppHost类,而不是依赖于我的program.cs中的一个,并声明如下:

public class RSWrapperServicesAppHostHttpListener
            : AppHostHttpListenerBase
{
    public RSWrapperServicesAppHostHttpListener()
        : base("RSWrapper Services Tests", typeof(DataRequestService).Assembly) { } 

// 'DataRequestService' is a random rest service class, 
// defined in the referenced services assembly

}

现在ServiceStack很高兴,我的测试又恢复了。

他们是如何工作的?最初一切都在一个项目中混杂在一起。一旦我将事物分成单独的程序集,即DTO,服务,业务逻辑和测试,我就把它打破了。但是由于我在让UI工作的同时暂时停止了单元测试,我立即没有注意到。