ASP.NET Web API のテスト
ASP.NET Web API ではルーティングが少し特殊なため、(特殊ではなく RESTful に沿っているだけですが)オレオレな API を定義してルーティングをカスタマイズすると、
すぐに ”マッチするアクションメソッドが複数あります”等のエラーが起きます。
API なのでエンドポイントを強固で正確なものにしたいため、
Writing tests for an ASP.NET Web API service を参考にしてテストを書きました。
(リンク先では三種類のテスト方法が記載されています。)
大雑把にまとめると以下の通りです。
- SelfHost は使用しない
- Unity を使って外部コンポーネントを利用しているので、Moq で置き換える。
- DpendencyResolver は Unity.WebAPI を利用。
テスト対象となる ApiController
namespace WebApiTestTrain.Controllers { public class PersonsController : ApiController { public PersonsController(IPersonService personService) { _personService = personService; } private IPersonService _personService; [HttpGet] public IEnumerable<Person> FindAll() { return _personService.FindAll(); } } }
テストコード
using System.Collections.Generic; using System.Linq; using System.Net; using System.Net.Http; using System.Threading; using System.Web.Http; using Microsoft.Practices.Unity; using Moq; using NUnit.Framework; using WebApiTestTrain.Models; namespace Test { [TestFixture] public class PersonApiTest { //IPersonServiceのモック Mock<IPersonService> personServiceMock = new Mock<IPersonService>(); [Test] public void FindAll_Test() { var config = new HttpConfiguration(); //WebApiTestTrain プロジェクトの API をテストしたい。 //HttpConfiguration に、対象プロジェクトの設定を反映させる。(ルーティングとかフォーマッタとか) WebApiTestTrain.WebApiConfig.Register(config); //Unityを使い、モックが使用されるようにDpendencyResolverを設定する。 UnitySetup(config); //IPersonServiceが返す値を設定する。 var persons = new Person[] { new Person() { Id = 1 }, new Person() { Id = 2 } }; personServiceMock.Setup(e => e.FindAll()) .Returns(persons); var httpServer = new HttpServer(config); using (var client = new HttpMessageInvoker(httpServer)) { using (var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost/api/persons/")) using (var response = client.SendAsync(request, CancellationToken.None).Result) { //検証 Assert.AreEqual(HttpStatusCode.OK, response.StatusCode); //値の検証 var actual = response.Content.ReadAsAsync<IEnumerable<Person>>().Result; Assert.AreEqual(2, actual.Count()); } } } /// <summary> /// Unityを使いDpendencyResolverを設定します。 /// </summary> /// <param name="config"></param> private void UnitySetup(HttpConfiguration config) { var container = new UnityContainer(); //IPersonServiceは、モックのインスタンスが使用されるよう登録する。 container.RegisterInstance<IPersonService>(personServiceMock.Object); //IDependencyResolverを登録 config.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container); } } }
煩雑なコードになりましたが、実際はこんな風にまとめています。
ASP.NET Web API は本当に柔軟です…。
ここまでくるとテストというよりは、Web API の別の形のように見えます。