web-dev-qa-db-ja.com

1つのソリューションでWebAPiをデバッグ/単体テストする方法

1対ソリューションでWebAPIを単体テストまたはデバッグする方法はありますか?私はHttpClientを使用してWebAPIを使用しており、これを行うためにVSの2つのインスタンスがあります。

1つのVSインスタンスでは単体テストがあり、2番目のVSインスタンスではローカルホストでwebapiが実行されています。

これを行うためのより良い方法はありますか?

単体テストの好ましい方法は、WebAPIプロジェクトへの参照を持つことですか?

HttpClientを使用して使用したいので、UnitTestプロジェクトで参照する必要はありません。

したがって、私のUnitTestメソッドでは、baseAddressは " http:// localhost:1234 "になります。

これは、同じソリューションから起動された場合にWebAPIがホストされる場所です。

私がデバッグしている現在の方法では、同じソリューションをロードして2番目のVisual Studioインスタンスを起動し、一方をWebAPIプロジェクトで実行し、もう一方のVisualStudioで単体テストプロジェクトを実行する必要があります。

15
Arcadian
  1. ユニットテストのデバッグを開始します
  2. テストコードの最初の行にある間、またはローカルWebAPIプロジェクトを呼び出す前
  3. Web APIプロジェクトを右クリックし、[デバッグ]> [新しいインスタンスの開始]を選択します
9
Barbaros Alp

それで、同僚と私は、提案された答えを試してみましたが、役に立ちませんでした。ただし、テストでデバッグモードになったら、IISプロセスに接続することで、これに対する解決策が実際に見つかりました。手順は次のとおりです。

  1. 単体テストプロジェクトとWebAPIプロジェクトが同じソリューションに含まれていることを確認してください。
  2. プロパティセクションでソリューションがシングルスタートアップに設定されていることを確認します(つまり、デフォルトのままにします)。
  3. デバッグするコントローラーメソッドのエンドポイントにブレークポイントを追加します。
  4. デバッグするテストにブレークポイントを追加し、右クリックして[テストのデバッグ]をクリックします(または、ReSharperなどのお気に入りのテストランナーを使用してデバッグします)。
  5. ブレークポイントに達したら、[デバッグ]、[デバッグ]の順にクリックします。プロセスにアタッチ...
  6. 特定のサービスのローカルIISプロセスを見つけてクリックし、[添付]をクリックします
  7. デバッグを続行し、サービスのブレークポイントがヒットするのを監視します

さらに簡単にするために、IISに自動的にアタッチするための拡張機能をダウンロードしました。これにより、[ツール]メニューにメニューバー項目が表示されます。

非常に簡単にするために、ツールバーセクションをカスタマイズしてメニューバーコマンドをツールバーに追加し、IISへのアタッチが1回クリックするだけで済むようにしました。

6
Britton

Daniel Mannが述べたように、これは単体テストではありません。これは統合テストです。プロジェクト全体を実行し、すべてをテストしています。

Webapiコントローラーの単体テストを行う場合は、単体テストプロジェクトをwebapiプロジェクトに追加し、単体テストを作成するだけです。一度に1つのクラスのみをテストすることに集中したいとします。そのクラスの依存関係をモック/偽造します。

これがMicrosoftの素晴らしい例です http://www.asp.net/web-api/overview/testing-and-debugging/unit-testing-with-aspnet-web-api

しかし、探しているのが単一のソリューションでのテストの実行である場合。両方のプロジェクトを同じソリューションに入れるだけです。ソリューションエクスプローラーでソリューションを右クリックします。 「スタートアッププロジェクトの設定」を選択します。 「複数のスタートアッププロジェクト」を選択し、同時にスタートアップしたいプロジェクトを選択します。

4
Fran

マイクが述べたように、WebAPIをセルフホストできます。

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

詳細については、 http://www.asp.net/web-api/overview/older-versions/self-Host-a-web-api

単体テストスイートを初期化するときにホスティングを開始し、テストスイートをクリーンアップするときにシャットダウンすることができます。

1

ASP.Net Coreの現在のバージョンでは、これに対する公式の解決策は、Microsoft.AspNetCore.TestHost Nuget Assemblyを使用して、テストプロジェクトでWebプロジェクトをホストするシミュレートされたWebサーバーを作成することです。

使用法の詳細はここで見つけることができます: https://docs.Microsoft.com/en-us/aspnet/core/testing/integration-testing

一方で、実際のWebサーバーが関与していない場合の本物の統合テストとはどのような定義であるかというと、少しファッジのように感じますが、セットアップすると、少なくともシームレスに機能します。

0
Neutrino

APIプロジェクトがあり、APIのエンドツーエンドの単体テストプロジェクトを作成した場合(つまり、HttpClient、WebClient、またはその他のhttpクライアントラッパーを使用してAPIを直接テストしている場合)、「複数のスタートアッププロジェクト」を有効にする必要があります。ソリューションに。以下の手順に従ってください。

  1. ソリューションファイルを右クリックして、プロパティを選択します。
  2. 「複数のスタートアッププロジェクト」ラジオボタンを選択します。
  3. WebAPIプロジェクトと単体テストプロジェクトのドロップダウンで[開始]アクションを選択します。
  4. F5をデバッグモードで開始します。
  5. 「出力型クラスライブラリを持つプロジェクトを直接開始することはできません」というエラーダイアログが表示されます。単体テストプロジェクトは単なるクラスライブラリであるため、これは問題ありません(実行可能ファイルではないため、main/startメソッドはありません)。ダイアログの「OK」をクリックするだけです。
  6. テストする単体テスト方法で、右クリックして[ユニットテストのデバッグ]を選択し、デバッグを開始します。
0
alltej

セルフホストを試しましたが、いくつか問題が発生します1。

HttpContext.Current is null
  1. Web APIカスタムエラーハンドラーがあり、セルフホストでは機能しません

IisExpressソリューションは私にとって非常にうまく機能します

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 

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

iisexpressにアタッチ

次に、デバッグテストでブレークポイントを作成し、[デバッグ]> [プロセスにアタッチ]> [アタッチ]で選択します enter image description here [OK]をクリックし、

iisexpressを検索し、[添付]をクリックします

0