LoginSignup
1
6

More than 5 years have passed since last update.

TestHostを用いたASP.NET Coreアプリケーションのテスト

Posted at

やること

Microsoft.AspNetCore.TestHostを使用して、ASP.NET Core Webアプリケーションをオンメモリにホストした状態でのテストを行います。

TestHostを用いることで、HTTPリクエストをエミュレートしたエンドツーエンドの試験が可能になります。

要は、Javaで埋め込みコンテナを使ってテストする~、みたいな奴のASP.NET Core版です。

環境

  • Visual Strudio 2015
  • .NET Core Tooling Preview 2 for Visual Studio 2015

前提

テスト対象となるASP.NET Core Webアプリケーションのプロジェクトが作成され、.NET Core 1.1へアップデート済みの状態とします。

また、今回はわかりやすいようにAPIコントローラーの呼び出しをテスト対象とするため、APIコントローラーを追加済みの状態とします。

サンプル

以下に完成形のサンプルを用意しています。

手順

テストプロジェクトの構築手順について記述します。

ASP.NET Coreアプリケーションのソリューションにテストプロジェクトとして「Class Library (.NET Core)」のプロジェクトを追加します。

作成されたプロジェクトはターゲットフレームワークが.NET Standardになっているため、そのままではASP.NET Coreアプリケーションのプロジェクトを参照できないのでproject.jsonの内容を変更します。

ターゲットフレームワークの変更と、必要なライブラリの参照を追加したproject.jsonは以下の様になります。

{
  "version": "1.0.0-*",

  "testRunner": "xunit",

  "dependencies": {
    "Microsoft.NETCore.App": {
      "type": "platform",
      "version": "1.1.0"
    },
    "dotnet-test-xunit": "2.2.0-preview2-build1029",
    "xunit": "2.2.0-beta4-build3444",
    "Microsoft.AspNetCore.TestHost": "1.1.0",
    "Microsoft.DotNet.InternalAbstractions": "1.0.0",
    "TestHostExample": "1.0.0-*"
  },

  "frameworks": {
    "netcoreapp1.1": {
      "imports": [
        "dotnet5.6",
        "portable-net45+win8"
      ]
    }
  }
}

行っている作業は以下になります。

  • .NETStandard 1.6の設定から.NETCoreApp 1.1用にdependenciesとframeworksを変更
  • testRunnerセクション追加
  • dotnet-test-xunit、xunitへの参照追加
  • Microsoft.AspNetCore.TestHostへの追加
  • Microsoft.DotNet.InternalAbstractionsへの追加
  • Webアプリケーションプロジェクト(TestHostExample)への参照の追加

なお、Microsoft.DotNet.InternalAbstractionsについては、1.0環境では問題ありませんが、Microsoft.AspNetCore.Mvcを1.1.0にあげると問題が発生する(Visual Studioのテストエクスプローラーにテストが表示されない、dotnet testコマンドによるテストでは例外が発生する)ため追加しています。

テストコード

テストコードは以下の内容となります。

using System.Net.Http;

using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.TestHost;
using Microsoft.Extensions.Configuration;

using Xunit;

public class ValuesControllerTest
{
    [Fact]
    public async void GetReturnValueArray()
    {
        var config = new ConfigurationBuilder().Build();

        var host = new WebHostBuilder()
            .UseConfiguration(config)
            .UseStartup<Startup>();

        var server = new TestServer(host);

        using (var client = server.CreateClient())
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "/api/values/");
            var response = await client.SendAsync(request);

            var content = await response.Content.ReadAsStringAsync();

            Assert.Equal(content, "[\"value1\",\"value2\"]");
        }
    }
}

テスト対象プロジェクトのStartupをホストしてTestServerのインスタンスを作成し、そこからクライアントの作成を行って、HTTPリクエスト/レスポンスのエミュレーションによるテスト内容になります。

テスト用のカスタマイズを行う場合、TestServerのインスタンス作成前にconfigやWebHostBuilderをいじったりします。

あとは、Visual Srudioのテストメニューやdotnet testコマンドによりテストを実行するだけです。

ホスティングまで疑似ってテストすると重いと思うかもしれませんが、テストの実行時間は1個目こそ500msくらいかかりますが、それ以降は10msくらいで終わるので気にしなくていいと思います。

うさコメ

ところで、Startup内でServiceProviderに登録しているコンポーネントについて、テスト用のモックへの置き換えはどこでやるのがええんやろね(・ω・)?

Startupのコンポーネント登録箇所をvirtualにしてそこで、とか?

1
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
6