1

在我的单页 Web 应用程序正常工作(使用 ServiceStack 的 RazorFormat() MVC,而不是 .ASP MVC 提供的网页)之后,我对该服务进行了(之前通过的)测试。测试失败。再次测试网络应用程序(调试运行,//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]
    }
}
4

1 回答 1

3

我升级到了最新的 ServiceStack - 3.9.55,还是不行。所以,我重新开始,从一开始就进行健全性检查。原来 program.cs ListeningOn 有http://*:1337/,而 nunit TestFixture ListeningOn 是http://localhost:1337/

检查 urlacl(以管理员身份)http://localhost:1337/

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

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

检查 urlacl(以管理员身份)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/ 不能用作通配符 url。

这是一个方便的代码片段,可帮助您构建 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 中实现了跟踪,如下所示:

<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 源代码,以便我可以单步执行代码并找出为什么我在测试中得到“未找到”,当它在我“调试/运行”并通过浏览器测试时工作时。事实证明,这RestHandler.FindMatchingRestPath(httpMethod, pathInfo, contentType)并没有返回匹配项。嗯。这是为什么?AppHost 的声明方式相同。那么,有什么不同呢?

其余服务位于我项目的主程序集中。从“调试/运行”运行时,默认程序集具有服务,并且一切正常。但是当从测试项目运行时,将服务程序集添加为引用,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 正常工作的同时暂时推迟了单元测试,所以我没有立即注意到。

于 2013-07-11T16:35:30.933 回答