How to debug/unit test webAPi in one solution

2020-06-08 13:04发布

Is there a way to unit test or debug a web api in one vs solution? I am consuming the WebAPI using HttpClient and have two instances of VS up to do this.

in 1 VS instance I have the unit test, in the second vs instance I have the webapi running in localhost.

Is there a better way to do this?

Is the preferred way to unit test is to have a reference to the WebAPI project?

I want to consume it using httpClient and not have to reference it in the UnitTest Project.

so in my UnitTest method it would have a baseAddress of "http://localhost:1234"

this would be where the WebAPI if launched from the same solution would be hosted.

The current way I am debugging requires me to launch a second Visual Studio instance with the same solution loaded and have one running the WebAPI project, while the other Visual Studio runs the Unit Test project.

7条回答
▲ chillily
2楼-- · 2020-06-08 13:34

In the current version of ASP.Net Core the official solution to this is to use the Microsoft.AspNetCore.TestHost Nuget assembly which creates a simulated web server hosting the web project in the test project.

Details on usage can be found here: https://docs.microsoft.com/en-us/aspnet/core/testing/integration-testing

On the one hand it feels like a bit of a fudge because by what definition is it genuine integration testing if a real web server is not involved, on the other hand it does at least work pretty seamlessly once you get it set up.

查看更多
可以哭但决不认输i
3楼-- · 2020-06-08 13:37

I try the selft hosted but I get some problens 1.

HttpContext.Current is null
  1. I have in the web api custom error handler and in self hosted don't work

IisExpress solution work for me very good

bathe file to deploy to iis

@Echo off 
set msBuildDir=C:\Program Files (x86)\MSBuild\14.0\Bin
::compile web api project
call "%msBuildDir%\msbuild.exe" solutionFilePath.sln /t:projectName /p:Configuration=Debug;TargetFrameworkVersion=v4.5 /l:FileLogger,Microsoft.Build.Engine;logfile=Manual_MSBuild_ReleaseVersion_LOG.log /p:Platform="Any CPU" /p:BuildProjectReferences=false

call "C:\Program Files (x86)\IIS Express\iisexpress.exe" /path:"pathToRootOfApiProject" /port:8888 /trace:error 

I work with Nunit frameWork

  [SetUpFixture]
    public class SetUpTest
    {
        private Process process = null;
        private Process IisProcess = null;
        private System.IO.StreamWriter sw = null;
        string programsFilePath = Environment.GetEnvironmentVariable(@"PROGRAMFILES(X86)");

        [OneTimeSetUp]
        public void Initialize()
        {
            //compile web api project
            List<string> commands = new List<string>();
            commands.Add($@"CD {programsFilePath}\MSBuild\14.0\Bin\");
            commands.Add($@"msbuild ""pathToYourSolution.sln"" /t:ProjrctName /p:Configuration=Debug;TargetFrameworkVersion=v4.5 /p:Platform=""Any CPU"" /p:BuildProjectReferences=false /p:VSToolsPath=""{programsFilePath}\MSBuild\Microsoft\VisualStudio\v14.0""");
            RunCommands(commands);

            //deploy to iis express
            RunIis();
        }



        [OneTimeTearDown]
        public void OneTimeTearDown()
        {
            if (IisProcess.HasExited == false)
            {
                IisProcess.Kill();
            }
        }

        void RunCommands(List<string> cmds, string workingDirectory = "")
        {
            if (process == null)
            {
                InitializeCmd(workingDirectory);
                sw = process.StandardInput;
            }

            foreach (var cmd in cmds)
            {
                sw.WriteLine(cmd);
            }
        }

        void InitializeCmd(string workingDirectory = "")
        {
            process = new Process();
            var psi = new ProcessStartInfo();
            psi.FileName = "cmd.exe";
            psi.RedirectStandardInput = true;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.UseShellExecute = false;
            psi.WorkingDirectory = workingDirectory;
            process.StartInfo = psi;
            process.Start();
            process.OutputDataReceived += (sender, e) => { Debug.WriteLine($"cmd output: {e.Data}"); };
            process.ErrorDataReceived += (sender, e) => { Debug.WriteLine($"cmd output: {e.Data}"); throw new Exception(e.Data); };
            process.BeginOutputReadLine();
            process.BeginErrorReadLine();
        }

        void RunIis()
        {
            string _port = System.Configuration.ConfigurationManager.AppSettings["requiredPort"];
            if (_port == 0)
            {
                throw new Exception("no value by config setting for 'requiredPort'");
            }

            IisProcess = new Process();
            var psi = new ProcessStartInfo();
            psi.FileName = $@"{programsFilePath}\IIS Express\iisexpress.exe";
            psi.Arguments = $@"/path:""pathToRootOfApiProject"" /port:{_port} /trace:error";
            psi.RedirectStandardInput = true;
            psi.RedirectStandardOutput = true;
            psi.RedirectStandardError = true;
            psi.UseShellExecute = false;
            IisProcess.StartInfo = psi;
            IisProcess.Start();
            IisProcess.OutputDataReceived += (sender, e) => { Debug.WriteLine($"cmd output: {e.Data}"); };
            IisProcess.ErrorDataReceived += (sender, e) =>
            {
                Debug.WriteLine($"cmd output: {e.Data}");
                if (e.Data != null)
                {
                    throw new Exception(e.Data);
                }
            };
            IisProcess.BeginOutputReadLine();
            IisProcess.BeginErrorReadLine();
        }
    }

attach to iisexpress

Debug test then make a breakpoint goto Debug>Attach to process> in the attach to select enter image description here click OK,

search iisexpress and click attach

查看更多
Lonely孤独者°
4楼-- · 2020-06-08 13:43
  1. Start debugging Unit Test
  2. While on the first line of your test code or before calling your local web api project
  3. Right click on your web api project and Debug > Start new instance
查看更多
Summer. ? 凉城
5楼-- · 2020-06-08 13:45

You can self host the web api as mike mentioned,

var config = new HttpSelfHostConfiguration("http://localhost:8080");

config.Routes.MapHttpRoute(
    "API Default", "api/{controller}/{id}", 
    new { id = RouteParameter.Optional });

using (HttpSelfHostServer server = new HttpSelfHostServer(config))
{
    server.OpenAsync().Wait();
    Console.WriteLine("Press Enter to quit.");
    Console.ReadLine();
}

for more details, http://www.asp.net/web-api/overview/older-versions/self-host-a-web-api

you could start the hosting when you initialize your unit test suite, and shutdown when you cleanup the test suite.

查看更多
Melony?
6楼-- · 2020-06-08 13:56

If you have an API project and you created an end-to-end unit test project for the API (meaning you are testing the API directly using HttpClient, WebClient, or other http client wrappers), you have to enable "Multiple startup projects" on the solution. Follow steps below:

  1. Right click on the solution file and select properties.
  2. Select "Multiple startup projects" radio button.
  3. Select the "Start" action in the drop-down for the web api project and unit test project.
  4. F5 to start in debug mode.
  5. You will get an error dialog saying "A project with an output type class library cannot be started directly". This is fine since the unit test project is just a class library (not an executable so there is no main/start method). Just click "Ok" the dialog.
  6. On the unit test method you want to test, right click and select "Debug Unit Tests" to start debugging.
查看更多
男人必须洒脱
7楼-- · 2020-06-08 13:59

So a colleague and I just tried the suggested answers to no avail. However, we have actually found a solution to this that works well by attaching to the IIS process once you are in debug mode on your test. Here are the steps:

  1. Ensure your unit-test project and Web API project are in the same solution.
  2. Ensure your solution is set single-startup in the properties section (i.e. leave as default).
  3. Add a breakpoint to the endpoint in your controller method that you want to debug.
  4. Add a breakpoint in your test that you want to debug and then right-click and hit "Debug Tests" (or use your favorite Test Runner like ReSharper to debug).
  5. Once your break point hits, click Debug | Attach to Process...
  6. Find and click on your local IIS process for the given service, then hit Attach
  7. Continue debugging and watch your breakpoint in your service get hit

For extra ease, we downloaded an extension for attaching to IIS automatically which gave us a menubar item in the Tools menu.

For superb ease we customized the toolbar section to add the menubar command to the toolbar so that attaching to IIS was one simple click.

查看更多
登录 后发表回答