当前位置:  开发笔记 > 编程语言 > 正文

NUnit与ASP.NET网站

如何解决《NUnit与ASP.NET网站》经验,为你挑选了1个好方法。

我正在尝试升级我们的构建服务器,从没有构建服务器到拥有一个!

我正在使用JetBrains的TeamCity(使用ReSharper几年,我相信他们的东西),并打算使用NUnit和MSBuild.

但是,我提出了一个问题:似乎无法使用NUnit测试ASP.NET网站.我曾经假设可以在构建之后将其配置为测试App_Code,但似乎很好地进行测试的唯一方法是将网站转换为Web应用程序(我的老板不喜欢这个想法).

我怎么能这样做?

请记住,测试需要能够从TeamCity自动触发.



1> Sky Sanders..:

如果您想对您的网站进行冒烟测试,或者在某些端点上进行测试,请参阅下面的代码.

另一方面,如果您想测试不可测试(可伪造的)ASP.NET网站程序集(而不是Web应用程序),那么就像他们在法国所说的那样,SOL

程序集是一个随机命名的动态编译程序集,深入框架临时ASP.NET文件的大小,使得测试几乎不可能.

你真的需要考虑几个选择:

    将需要测试的逻辑放在单独的程序集中.

    更改为提供可测试程序集的Web应用程序项目.

对不起,我不认为你会找到你想要的,但我可能是错的.让我们来看看.

祝好运


下载带有站点和应用程序的Visual Studio 2008示例.

我写了一个包装器,WebHost.WebServer.dll它是开发服务器的核心,在CI中运行良好.我用它所有的时间.

这是一个缩小版本,包括一个用法示例.

test.cs中

using System.Net;
using NUnit.Framework;

namespace Salient.Excerpts
{
    [TestFixture]
    public class WebHostServerFixture : WebHostServer
    {
        [TestFixtureSetUp]
        public void TestFixtureSetUp()
        {
            // debug/bin/testproject/solution/siteundertest - make sense?
            StartServer(@"..\..\..\..\TestSite");

            // is the equivalent of
            // StartServer(@"..\..\..\..\TestSite",
            // GetAvailablePort(8000, 10000, IPAddress.Loopback, true), "/", "localhost");
        }
        [TestFixtureTearDown]
        public void TestFixtureTearDown()
        {
            StopServer();
        }

        [Test]
        public void Test()
        {
            // while a reference to the web app under test is not necessary,
            // if you do add a reference to this test project you may F5 debug your tests.
            // if you debug this test you will break in Default.aspx.cs
            string html = new WebClient().DownloadString(NormalizeUri("Default.aspx"));
        }
    }
}

WebHostServer.cs

// Project: Salient
// http://salient.codeplex.com
// Date: April 16 2010

using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.NetworkInformation;
using System.Threading;
using Microsoft.VisualStudio.WebHost;

namespace Salient.Excerpts
{
    /// 
    /// A general purpose Microsoft.VisualStudio.WebHost.Server test fixture.
    /// WebHost.Server is the core of the Visual Studio Development Server (WebDev.WebServer).
    ///
    /// This server is run in-process and may be used in F5 debugging.
    /// 
    /// 
    /// If you are adding this source code to a new project, You will need to
    /// manually add a reference to WebDev.WebHost.dll to your project. It cannot
    /// be added from within Visual Studio.
    ///
    /// Please see the Readme.txt accompanying this code for details.
    /// 
    /// NOTE: code from various namespaces/classes in the Salient project have been merged into this
    /// single class for this post in the interest of brevity
    public class WebHostServer
    {
        private Server _server;

        public string ApplicationPath { get; private set; }

        public string HostName { get; private set; }

        public int Port { get; private set; }

        public string VirtualPath { get; private set; }

        public string RootUrl
        {
            get { return string.Format(CultureInfo.InvariantCulture, "http://{0}:{1}{2}", HostName, Port, VirtualPath); }
        }

        /// 
        /// Combine the RootUrl of the running web application with the relative url specified.
        /// 
        public virtual Uri NormalizeUri(string relativeUrl)
        {
            return new Uri(RootUrl + relativeUrl);
        }

        /// 
        /// Will start "localhost" on first available port in the range 8000-10000 with vpath "/"
        /// 
        /// 
        public void StartServer(string applicationPath)
        {
            StartServer(applicationPath, GetAvailablePort(8000, 10000, IPAddress.Loopback, true), "/", "localhost");
        }

        /// 
        /// 
        /// Physical path to application.
        /// Port to listen on.
        /// Optional. defaults to "/"
        /// Optional. Is used to construct RootUrl. Defaults to "localhost"
        public void StartServer(string applicationPath, int port, string virtualPath, string hostName)
        {
            if (_server != null)
            {
                throw new InvalidOperationException("Server already started");
            }

            // WebHost.Server will not run on any other IP
            IPAddress ipAddress = IPAddress.Loopback;

            if(!IsPortAvailable(ipAddress, port))
            {
                throw new Exception(string.Format("Port {0} is in use.", port));
            }

            applicationPath = Path.GetFullPath(applicationPath);

            virtualPath = String.Format("/{0}/", (virtualPath ?? string.Empty).Trim('/')).Replace("//", "/");

            _server = new Server(port, virtualPath, applicationPath, false, false);
            _server.Start();

            ApplicationPath = applicationPath;
            Port = port;
            VirtualPath = virtualPath;
            HostName = string.IsNullOrEmpty(hostName) ? "localhost" : hostName;
        }

        /// 
        /// Stops the server.
        /// 
        public void StopServer()
        {
            if (_server != null)
            {
                _server.Stop();
                _server = null;
                // allow some time to release the port
                Thread.Sleep(100);
            }
        }

        public void Dispose()
        {
            StopServer();
        }


       /// 
        /// Gently polls specified IP:Port to determine if it is available.
        /// 
        /// 
        /// 
        public static bool IsPortAvailable(IPAddress ipAddress, int port)
        {
            bool portAvailable = false;

            for (int i = 0; i < 5; i++)
            {
                portAvailable = GetAvailablePort(port, port, ipAddress, true) == port;
                if (portAvailable)
                {
                    break;
                }
                // be a little patient and wait for the port if necessary,
                // the previous occupant may have just vacated
                Thread.Sleep(100);
            }
            return portAvailable;
        }

        /// 
        /// Returns first available port on the specified IP address.
        /// The port scan excludes ports that are open on ANY loopback adapter.
        ///
        /// If the address upon which a port is requested is an 'ANY' address all
        /// ports that are open on ANY IP are excluded.
        /// 
        /// 
        /// 
        /// The IP address upon which to search for available port.
        /// If true includes ports in TIME_WAIT state in results.
        /// TIME_WAIT state is typically cool down period for recently released ports.
        /// 
        public static int GetAvailablePort(int rangeStart, int rangeEnd, IPAddress ip, bool includeIdlePorts)
        {
            IPGlobalProperties ipProps = IPGlobalProperties.GetIPGlobalProperties();

            // if the ip we want a port on is an 'any' or loopback port we need to exclude all ports that are active on any IP
            Func isIpAnyOrLoopBack = i => IPAddress.Any.Equals(i) ||
                                                           IPAddress.IPv6Any.Equals(i) ||
                                                           IPAddress.Loopback.Equals(i) ||
                                                           IPAddress.IPv6Loopback.
                                                               Equals(i);
            // get all active ports on specified IP.
            List excludedPorts = new List();

            // if a port is open on an 'any' or 'loopback' interface then include it in the excludedPorts
            excludedPorts.AddRange(from n in ipProps.GetActiveTcpConnections()
                                   where
                                       n.LocalEndPoint.Port >= rangeStart &&
                                       n.LocalEndPoint.Port <= rangeEnd && (
                                       isIpAnyOrLoopBack(ip) || n.LocalEndPoint.Address.Equals(ip) ||
                                        isIpAnyOrLoopBack(n.LocalEndPoint.Address)) &&
                                        (!includeIdlePorts || n.State != TcpState.TimeWait)
                                   select (ushort)n.LocalEndPoint.Port);

            excludedPorts.AddRange(from n in ipProps.GetActiveTcpListeners()
                                   where n.Port >= rangeStart && n.Port <= rangeEnd && (
                                   isIpAnyOrLoopBack(ip) || n.Address.Equals(ip) || isIpAnyOrLoopBack(n.Address))
                                   select (ushort)n.Port);

            excludedPorts.AddRange(from n in ipProps.GetActiveUdpListeners()
                                   where n.Port >= rangeStart && n.Port <= rangeEnd && (
                                   isIpAnyOrLoopBack(ip) || n.Address.Equals(ip) || isIpAnyOrLoopBack(n.Address))
                                   select (ushort)n.Port);

            excludedPorts.Sort();

            for (int port = rangeStart; port <= rangeEnd; port++)
            {
                if (!excludedPorts.Contains((ushort)port))
                {
                    return port;
                }
            }

            return 0;
        }
    }
}

注意:Microsoft.VisualStudio.WebHost命名空间包含在文件中WebDev.WebHost.dll.此文件位于GAC中,但无法在Visual Studio中添加对此程序集的引用.

要添加引用,您需要在文本编辑器中打开.csproj文件并手动添加引用.

查找ItemGroup包含项目引用的内容并添加以下元素:


  False

参考:http://www.codeproject.com/KB/aspnet/test-with-vs-devserver-2.aspx

推荐阅读
惬听风吟jyy_802
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有