1. <ul id="0c1fb"></ul>

      <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
      <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区

      RELATEED CONSULTING
      相關(guān)咨詢
      選擇下列產(chǎn)品馬上在線溝通
      服務(wù)時間:8:30-17:00
      你可能遇到了下面的問題
      關(guān)閉右側(cè)工具欄

      新聞中心

      這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
      ASP.NETWebAPI單元測試-單元測試

      今天來到了最后的壓軸章節(jié):單元測試

      十年的安溪網(wǎng)站建設(shè)經(jīng)驗(yàn),針對設(shè)計(jì)、前端、開發(fā)、售后、文案、推廣等六對一服務(wù),響應(yīng)快,48小時及時工作處理。成都營銷網(wǎng)站建設(shè)的優(yōu)勢是能夠根據(jù)用戶設(shè)備顯示端的尺寸不同,自動調(diào)整安溪建站的顯示方式,使網(wǎng)站能夠適用不同顯示終端,在瀏覽器中調(diào)整網(wǎng)站的寬度,無論在任何一種瀏覽器上瀏覽網(wǎng)站,都能展現(xiàn)優(yōu)雅布局與設(shè)計(jì),從而大程度地提升瀏覽體驗(yàn)。創(chuàng)新互聯(lián)建站從事“安溪網(wǎng)站設(shè)計(jì)”,“安溪網(wǎng)站推廣”以來,每個客戶項(xiàng)目都認(rèn)真落實(shí)執(zhí)行。

      我們已經(jīng)有了完整的程序結(jié)構(gòu),現(xiàn)在是時候來對我們的組件做單元測試了。

      在UnitTestingWebAPI.Tests類庫上添加UnitTestingWebAPI.Domain, UnitTestingWebAPI.Data, UnitTestingWebAPI.Service和UnitTestingWebAPI.API.Core 同樣要安裝下列的Nuget 包:

      1. Entity Framework

      2. Microsoft.AspNet.WebApi.Core

      3. Microsoft.AspNet.WebApi.Client

      4. Microsoft.AspNet.WebApi.Owin

      5. Microsoft.AspNet.WebApi.SelfHost

      6. Micoroft.Owin

      7. Owin

      8. Micoroft.Owin.Hosting

      9. Micoroft.Owin.Host.HttpListener

      10. Autofac.WebApi2

      11. NUnit

      12. NUnitTestAdapter

      從清單中可知,我們將用NUnit 來寫單元測試

      Services 單元測試


      寫單元測試的第一件事是需要去設(shè)置或初始化一些單元測試中要用到的變量,NUnit框架則給要測試的方法添加Setup特性,在任何其他的NUnit測試開始之前,這一方法會先執(zhí)行,把Services層注入到Controller的構(gòu)造函數(shù)之后的第一件事就是進(jìn)行單元測試。因此在對WebAPI進(jìn)行單元測試之前需要仿造Repositories和Service。

      在這個例子中會看到如何仿造ArticleService, 并在這個Service的構(gòu)造函數(shù)中注入IArticleRepository和IUnitOfWork,所以我們需要創(chuàng)建兩個"特別的"實(shí)例來注入。

      ArticleService Constructor

      private readonly IArticleRepository articlesRepository;
      private readonly IUnitOfWork unitOfWork;
      
      public ArticleService(IArticleRepository articlesRepository, IUnitOfWork unitOfWork)
      {
          this.articlesRepository = articlesRepository;
          this.unitOfWork = unitOfWork;
      }

      這里的"特別的",是因?yàn)檫@些實(shí)例不是真正訪問數(shù)據(jù)庫的實(shí)例.

      注意

      單元測試必須運(yùn)行在內(nèi)存中并且不應(yīng)該訪問數(shù)據(jù)庫. 所有核心的方法必須通過像我們的例子中用Mock這樣的框架仿造。這個方式自動的測試會更快些。單元測試最基本的目的是更多的測試組件的行為,而不是真正的結(jié)果.

      開始測試ArticleService,創(chuàng)建一個ServiceTests的文件并添加下列代碼:

      [TestFixture]
      public class ServicesTests
      {
          #region Variables
          IArticleService _articleService;
          IArticleRepository _articleRepository;
          IUnitOfWork _unitOfWork;
          List
       _randomArticles;     #endregion       #region Setup     [SetUp]     public void Setup()     {         _randomArticles = SetupArticles();           _articleRepository = SetupArticleRepository();         _unitOfWork = new Mock().Object;         _articleService = new ArticleService(_articleRepository, _unitOfWork);     }       public List
       SetupArticles()     {         int _counter = new int();         List
       _articles = BloggerInitializer.GetAllArticles();           foreach (Article _article in _articles)             _article.ID = ++_counter;           return _articles;     }     public IArticleRepository SetupArticleRepository()     {         // Init repository         var repo = new Mock();         // Setup mocking behavior         repo.Setup(r => r.GetAll()).Returns(_randomArticles);         repo.Setup(r => r.GetById(It.IsAny()))             .Returns(new Func(                 id => _randomArticles.Find(a => a.ID.Equals(id))));         repo.Setup(r => r.Add(It.IsAny
      ()))             .Callback(new Action
      (newArticle =>             {                 dynamic maxArticleID = _randomArticles.Last().ID;                 newArticle.ID = maxArticleID + 1;                 newArticle.DateCreated = DateTime.Now;                 _randomArticles.Add(newArticle);             }));         repo.Setup(r => r.Update(It.IsAny
      ()))             .Callback(new Action
      (x =>             {                 var oldArticle = _randomArticles.Find(a => a.ID == x.ID);                 oldArticle.DateEdited = DateTime.Now;                 oldArticle = x;             }));         repo.Setup(r => r.Delete(It.IsAny
      ()))             .Callback(new Action
      (x =>             {                 var _articleToRemove = _randomArticles.Find(a => a.ID == x.ID);                 if (_articleToRemove != null)                     _randomArticles.Remove(_articleToRemove);             }));         // Return mock implementation         return repo.Object;     }       #endregion }

      如果你直接copy代碼可能會報(bào)錯:

      One or more types required to compile a dynaic expression ....

      ASP.NET Web API 單元測試 - 單元測試解決辦法:

      在Assembiles中添加Microsoft.CSharp.dll

      ASP.NET Web API 單元測試 - 單元測試

      在SetupArticleRepository()方法中我們模仿了_articleRepository的行為,換句話說,當(dāng)一個特定的方法使用了這個Reporistory的實(shí)例,就會得到我們所期待的結(jié)果。然后我們在_articleService的構(gòu)造函數(shù)中注入這個實(shí)例。我們用下面代碼測試_articleService.GetArticles()的行為是否是我們所期待的.

      ServiceShouldReturnAllArticles Test

      [Test]
      public void ServiceShouldReturnAllArticles()
      {
          var articles = _articleService.GetArticles();
      
          NUnit.Framework.Assert.That(articles, Is.EqualTo(_randomArticles));
      }

      編譯項(xiàng)目,運(yùn)行測試,要確保這個測試變?yōu)榫G色通過狀態(tài),用同樣的方式創(chuàng)建下面的測試:

      Services Test

      [Test]
      public void ServiceShouldReturnRightArticle()
      {
          var wcfSecurityArticle = _articleService.GetArticle(2);
      
          NUnit.Framework.Assert.That(wcfSecurityArticle,
              Is.EqualTo(_randomArticles.Find(a => a.Title.Contains("Secure WCF Services"))));
      }
      
      [Test]
      public void ServiceShouldAddNewArticle()
      {
          var _newArticle = new Article()
          {
              Author = "Chris Sakellarios",
              Contents = "If you are an ASP.NET MVC developer, you will certainly..",
              Title = "URL Rooting in ASP.NET (Web Forms)",
              URL = "https://chsakell.com/2013/12/15/url-rooting-in-asp-net-web-forms/"
          };
      
          int _maxArticleIDBeforeAdd = _randomArticles.Max(a => a.ID);
          _articleService.CreateArticle(_newArticle);
      
          NUnit.Framework.Assert.That(_newArticle, Is.EqualTo(_randomArticles.Last()));
          NUnit.Framework.Assert.That(_maxArticleIDBeforeAdd + 1, Is.EqualTo(_randomArticles.Last().ID));
      }
      
      [Test]
      public void ServiceShouldUpdateArticle()
      {
          var _firstArticle = _randomArticles.First();
      
          _firstArticle.Title = "OData feat. ASP.NET Web API"; // reversed
          _firstArticle.URL = "http://t.co/fuIbNoc7Zh"; // short link
          _articleService.UpdateArticle(_firstArticle);
      
          NUnit.Framework.Assert.That(_firstArticle.DateEdited, Is.Not.EqualTo(DateTime.MinValue));
          NUnit.Framework.Assert.That(_firstArticle.URL, Is.EqualTo("http://t.co/fuIbNoc7Zh"));
          NUnit.Framework.Assert.That(_firstArticle.ID, Is.EqualTo(1)); // hasn't changed
      }
      
      [Test]
      public void ServiceShouldDeleteArticle()
      {
          int maxID = _randomArticles.Max(a => a.ID); // Before removal
          var _lastArticle = _randomArticles.Last();
      
          // Remove last article
          _articleService.DeleteArticle(_lastArticle);
      
          NUnit.Framework.Assert.That(maxID, Is.GreaterThan(_randomArticles.Max(a => a.ID))); // Max reduced by 1
      }

      WebAPI 控制器單元測試

      在熟悉了偽造Services行為測試的基礎(chǔ)上,來進(jìn)行WebAPI控制器的單元測試。

      第一件事:設(shè)置在測試中需要的變量。

      用下面的代碼創(chuàng)建用于測試的控制器:

          [TestFixture]
          public class ControllerTests
          {
              #region Variables
              IArticleService _articleService;
              IArticleRepository _articleRepository;
              IUnitOfWork _unitOfWork;
              List
       _randomArticles;         #endregion         #region Setup         [SetUp]         public void Setup()         {             _randomArticles = SetupArticles();             _articleRepository = SetupArticleRepository();             _unitOfWork = new Mock().Object;             _articleService = new ArticleService(_articleRepository, _unitOfWork);         }         ///          /// Setup Articles         ///          ///          public List
       SetupArticles()         {             int _counter = new int();             List
       _articles = BloggerInitializer.GetAllArticles();             foreach (Article _article in _articles)                 _article.ID = ++_counter;             return _articles;         }         ///          /// Emulate _articleRepository behavior         ///          ///          public IArticleRepository SetupArticleRepository()         {             // Init repository             var repo = new Mock();             // Get all articles             repo.Setup(r => r.GetAll()).Returns(_randomArticles);             // Get Article by id             repo.Setup(r => r.GetById(It.IsAny()))                 .Returns(new Func(                     id => _randomArticles.Find(a => a.ID.Equals(id))));             // Add Article             repo.Setup(r => r.Add(It.IsAny
      ()))                 .Callback(new Action
      (newArticle =>                 {                     dynamic maxArticleID = _randomArticles.Last().ID;                     newArticle.ID = maxArticleID + 1;                     newArticle.DateCreated = DateTime.Now;                     _randomArticles.Add(newArticle);                 }));             // Update Article             repo.Setup(r => r.Update(It.IsAny
      ()))                 .Callback(new Action
      (x =>                 {                     var oldArticle = _randomArticles.Find(a => a.ID == x.ID);                     oldArticle.DateEdited = DateTime.Now;                     oldArticle.URL = x.URL;                     oldArticle.Title = x.Title;                     oldArticle.Contents = x.Contents;                     oldArticle.BlogID = x.BlogID;                 }));             // Delete Article             repo.Setup(r => r.Delete(It.IsAny
      ()))                 .Callback(new Action
      (x =>                 {                     var _articleToRemove = _randomArticles.Find(a => a.ID == x.ID);                     if (_articleToRemove != null)                         _randomArticles.Remove(_articleToRemove);                 }));             // Return mock implementation             return repo.Object;         }         #endregion     }

      控制器的類和其它的類一樣,所以我們可以分開各自測試。下面測試_articlesController.GetArticles(),看看是否能返回所有的文章。

      [Test]
      public void ControlerShouldReturnAllArticles()
      {
          var _articlesController = new ArticlesController(_articleService);
      
          var result = _articlesController.GetArticles();
      
          CollectionAssert.AreEqual(result, _randomArticles);
      }

      請確保測試已綠色通過,我們初始化了3條數(shù)據(jù),用_articlesController.GetArticle(3)測試看看能否返回最后一條。

      [Test]
      public void ControlerShouldReturnLastArticle()
      {
          var _articlesController = new ArticlesController(_articleService);
      
          var result = _articlesController.GetArticle(3) as OkNegotiatedContentResult
      ;     Assert.IsNotNull(result);     Assert.AreEqual(result.Content.Title, _randomArticles.Last().Title); }

      測試一個無效的Update操作,必須失敗并且返回一個BadRequestResult, 重新調(diào)用設(shè)置在_articleRepository上的Update操作。

      repo.Setup(r => r.Update(It.IsAny
      ()))     .Callback(new Action
      (x =>     {         var oldArticle = _randomArticles.Find(a => a.ID == x.ID);         oldArticle.DateEdited = DateTime.Now;         oldArticle.URL = x.URL;         oldArticle.Title = x.Title;         oldArticle.Contents = x.Contents;         oldArticle.BlogID = x.BlogID;     }));

      所以,當(dāng)我們測試一個不存在的文章就應(yīng)該返回失敗信息。

      [Test]
      public void ControlerShouldPutReturnBadRequestResult()
      {
          var _articlesController = new ArticlesController(_articleService)
          {
              Configuration = new HttpConfiguration(),
              Request = new HttpRequestMessage
              {
                  Method = HttpMethod.Put,
                  RequestUri = new Uri("http://localhost/api/articles/-1")
              }
          };
      
          var badresult = _articlesController.PutArticle(-1, new Article() { Title = "Unknown Article" });
          Assert.That(badresult, Is.TypeOf());
      }

      通過分別成功更新第一篇文章、發(fā)表一篇新文章、發(fā)布失敗一篇文章來完成我們的單元測試。

      Controller 單元測試

      [Test]
      public void ControlerShouldPutUpdateFirstArticle()
      {
          var _articlesController = new ArticlesController(_articleService)
          {
              Configuration = new HttpConfiguration(),
              Request = new HttpRequestMessage
              {
                  Method = HttpMethod.Put,
                  RequestUri = new Uri("http://localhost/api/articles/1")
              }
          };
      
          IHttpActionResult updateResult = _articlesController.PutArticle(1, new Article()
          {
              ID = 1,
              Title = "ASP.NET Web API feat. OData",
              URL = "http://t.co/fuIbNoc7Zh",
              Contents = @"OData is an open standard protocol.."
          }) as IHttpActionResult;
      
          Assert.That(updateResult, Is.TypeOf());
      
          StatusCodeResult statusCodeResult = updateResult as StatusCodeResult;
      
          Assert.That(statusCodeResult.StatusCode, Is.EqualTo(HttpStatusCode.NoContent));
      
          Assert.That(_randomArticles.First().URL, Is.EqualTo("http://t.co/fuIbNoc7Zh"));
      }
      
      [Test]
      public void ControlerShouldPostNewArticle()
      {
          var article = new Article
          {
              Title = "Web API Unit Testing",
              URL = "https://chsakell.com/web-api-unit-testing",
              Author = "Chris Sakellarios",
              DateCreated = DateTime.Now,
              Contents = "Unit testing Web API.."
          };
      
          var _articlesController = new ArticlesController(_articleService)
          {
              Configuration = new HttpConfiguration(),
              Request = new HttpRequestMessage
              {
                  Method = HttpMethod.Post,
                  RequestUri = new Uri("http://localhost/api/articles")
              }
          };
      
          _articlesController.Configuration.MapHttpAttributeRoutes();
          _articlesController.Configuration.EnsureInitialized();
          _articlesController.RequestContext.RouteData = new HttpRouteData(
          new HttpRoute(), new HttpRouteValueDictionary { { "_articlesController", "Articles" } });
          var result = _articlesController.PostArticle(article) as CreatedAtRouteNegotiatedContentResult
      ;     Assert.That(result.RouteName, Is.EqualTo("DefaultApi"));     Assert.That(result.Content.ID, Is.EqualTo(result.RouteValues["id"]));     Assert.That(result.Content.ID, Is.EqualTo(_randomArticles.Max(a => a.ID))); } [Test] public void ControlerShouldNotPostNewArticle() {     var article = new Article     {         Title = "Web API Unit Testing",         URL = "https://chsakell.com/web-api-unit-testing",         Author = "Chris Sakellarios",         DateCreated = DateTime.Now,         Contents = null     };     var _articlesController = new ArticlesController(_articleService)     {         Configuration = new HttpConfiguration(),         Request = new HttpRequestMessage         {             Method = HttpMethod.Post,             RequestUri = new Uri("http://localhost/api/articles")         }     };          _articlesController.Configuration.MapHttpAttributeRoutes();     _articlesController.Configuration.EnsureInitialized();     _articlesController.RequestContext.RouteData = new HttpRouteData(     new HttpRoute(), new HttpRouteValueDictionary { { "Controller", "Articles" } });     _articlesController.ModelState.AddModelError("Contents", "Contents is required field");     var result = _articlesController.PostArticle(article) as InvalidModelStateResult;     Assert.That(result.ModelState.Count, Is.EqualTo(1));     Assert.That(result.ModelState.IsValid, Is.EqualTo(false)); }

      上面測試的重點(diǎn),我們請求的幾個方面:返回碼或路由屬性。

      管理 Handler單元測試

      你可以通過創(chuàng)建HttpMessageInvoker的實(shí)例來測試Message Handler, 解析你要測試的Handler實(shí)例并調(diào)用SendAsync 方法。創(chuàng)建一個MessageHandlerTest.cs文件,并貼上下面的啟動設(shè)置代碼

      #region Variables
      private EndRequestHandler _endRequestHandler;
      private HeaderAppenderHandler _headerAppenderHandler;
      #endregion
      
      #region Setup
      [SetUp]
      public void Setup()
      {
          // Direct MessageHandler test
          _endRequestHandler = new EndRequestHandler();
          _headerAppenderHandler = new HeaderAppenderHandler()
          {
              InnerHandler = _endRequestHandler
          };
      }
      #endregion

      我們在HeaderAppenderHandler的內(nèi)部設(shè)置另外一個可以終止請求的Hanlder.只要Uri中包含一個測試字符,從新調(diào)用EndRequestHandler將會終止請求.現(xiàn)在來測試.

      [Test]
      public async void ShouldAppendCustomHeader()
      {
          var invoker = new HttpMessageInvoker(_headerAppenderHandler);
          var result = await invoker.SendAsync(new HttpRequestMessage(HttpMethod.Get,
              new Uri("http://localhost/api/test/")), CancellationToken.None);
      
          Assert.That(result.Headers.Contains("X-WebAPI-Header"), Is.True);
          Assert.That(result.Content.ReadAsStringAsync().Result,
              Is.EqualTo("Unit testing message handlers!"));
      }

      假如要做一個集成測試:當(dāng)一個請求被消息管道分配到Controller的Action的真實(shí)behavior。

      這將需要運(yùn)行WebApi,然后運(yùn)行單元測試。怎么做呢?必須是 通過Self host的模式運(yùn)行API,然后設(shè)置恰當(dāng)?shù)呐渲谩?/p>

      在UnitTestingWebAPI.Tests的項(xiàng)目中添加Startup.cs文件:

      Hosting/Startup.cs

      public class Startup
      {
          public void Configuration(IAppBuilder appBuilder)
          {
              var config = new HttpConfiguration();
              config.MessageHandlers.Add(new HeaderAppenderHandler());
              config.MessageHandlers.Add(new EndRequestHandler());
              config.Filters.Add(new ArticlesReversedFilter());
              config.Services.Replace(typeof(IAssembliesResolver), new CustomAssembliesResolver());
      
              config.Routes.MapHttpRoute(
                  name: "DefaultApi",
                  routeTemplate: "api/{controller}/{id}",
                  defaults: new { id = RouteParameter.Optional }
              );
              config.MapHttpAttributeRoutes();
      
              // Autofac configuration
              var builder = new ContainerBuilder();
              builder.RegisterApiControllers(typeof(ArticlesController).Assembly);
      
              // Unit of Work
              var _unitOfWork = new Mock();
              builder.RegisterInstance(_unitOfWork.Object).As();
      
              //Repositories
              var _articlesRepository = new Mock();
              _articlesRepository.Setup(x => x.GetAll()).Returns(
                      BloggerInitializer.GetAllArticles()
                  );
              builder.RegisterInstance(_articlesRepository.Object).As();
      
              var _blogsRepository = new Mock();
              _blogsRepository.Setup(x => x.GetAll()).Returns(
                  BloggerInitializer.GetBlogs
                  );
              builder.RegisterInstance(_blogsRepository.Object).As();
      
              // Services
              builder.RegisterAssemblyTypes(typeof(ArticleService).Assembly)
                  .Where(t => t.Name.EndsWith("Service"))
                  .AsImplementedInterfaces().InstancePerRequest();
      
              builder.RegisterInstance(new ArticleService(_articlesRepository.Object, _unitOfWork.Object));
              builder.RegisterInstance(new BlogService(_blogsRepository.Object, _unitOfWork.Object));
      
              IContainer container = builder.Build();
              config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
      
              appBuilder.UseWebApi(config);
          }
      }

      可能注意到和UnitTestingWebAPI.API里的WebSetup類的不同之處在與,這里我們用了假的Repositories和Services。

      返回到ControllerTests.cs中。

      [Test]
      public void ShouldCallToControllerActionAppendCustomHeader()
      {
          //Arrange
          var address = "http://localhost:9000/";
      
          using (WebApp.Start(address))
          {
              HttpClient _client = new HttpClient();
              var response = _client.GetAsync(address + "api/articles").Result;
      
              Assert.That(response.Headers.Contains("X-WebAPI-Header"), Is.True);
      
              var _returnedArticles = response.Content.ReadAsAsync>().Result;
              Assert.That(_returnedArticles.Count, Is.EqualTo(BloggerInitializer.GetAllArticles().Count));
          }
      }

      媒體類型格式化器 測試

      我們在UnitTestingWebAPI.API.Core中創(chuàng)建了ArticleFormatter,現(xiàn)在測試一下,應(yīng)該返回用逗號分割的文章字符串。它只能是寫文章的實(shí)例,但不能讀或者明白其它類型的類。為了應(yīng)用這個格式化器需要設(shè)置請求頭信息的Accept為application/article

      [TestFixture]
      public class MediaTypeFormatterTests
      {
          #region Variables
          Blog _blog;
          Article _article;
          ArticleFormatter _formatter;
          #endregion
      
          #region Setup
          [SetUp]
          public void Setup()
          {
              _blog = BloggerInitializer.GetBlogs().First();
              _article = BloggerInitializer.GetChsakellsArticles().First();
              _formatter = new ArticleFormatter();
          }
          #endregion
      }

      我們可以創(chuàng)建一個ObjectContent來測試MediaTypeFormatter,傳遞一個對象來檢查是否能被被格式化,如果格式化器不能讀和寫傳遞過去的對象則會拋出異常,例如,文章的格式化器不能識別Blog對象:

      [Test]
      public void FormatterShouldThrowExceptionWhenUnsupportedType()
      {
          Assert.Throws(() => new ObjectContent(_blog, _formatter));
      }

      換句話說,傳一個Article對象就一定會通過測試

      [Test]
      public void FormatterShouldNotThrowExceptionWhenArticle()
      {
          Assert.DoesNotThrow(() => new ObjectContent
      (_article, _formatter)); }

      用下面的代碼測試不符合MediaType formatter的Media type

      Media Type Formatters Unit tests

      [Test]
      public void FormatterShouldHeaderBeSetCorrectly()
      {
          var content = new ObjectContent
      (_article, new ArticleFormatter());     Assert.That(content.Headers.ContentType.MediaType, Is.EqualTo("application/article")); } [Test] public async void FormatterShouldBeAbleToDeserializeArticle() {     var content = new ObjectContent
      (_article, _formatter);     var deserializedItem = await content.ReadAsAsync
      (new[] { _formatter });     Assert.That(_article, Is.SameAs(deserializedItem)); } [Test] public void FormatterShouldNotBeAbleToWriteUnsupportedType() {     var canWriteBlog = _formatter.CanWriteType(typeof(Blog));     Assert.That(canWriteBlog, Is.False); } [Test] public void FormatterShouldBeAbleToWriteArticle() {     var canWriteArticle = _formatter.CanWriteType(typeof(Article));     Assert.That(canWriteArticle, Is.True); }

      路由測試

      在不Host Web API的情況下,測試路由配置。為了這個目的,需要一個可以從HttpControllerContext的實(shí)例中返回Controllerl類型或Controller中Action的幫助類,在測試之前,先創(chuàng)建一個路由配置的HttpConfiguration

      Helpers/ControllerActionSelector.cs

      public class ControllerActionSelector
      {
          #region Variables
          HttpConfiguration config;
          HttpRequestMessage request;
          IHttpRouteData routeData;
          IHttpControllerSelector controllerSelector;
          HttpControllerContext controllerContext;
          #endregion
      
          #region Constructor
          public ControllerActionSelector(HttpConfiguration conf, HttpRequestMessage req)
          {
              config = conf;
              request = req;
              routeData = config.Routes.GetRouteData(request);
              request.Properties[HttpPropertyKeys.HttpRouteDataKey] = routeData;
              controllerSelector = new DefaultHttpControllerSelector(config);
              controllerContext = new HttpControllerContext(config, routeData, request);
          }
          #endregion
      
          #region Methods
          public string GetActionName()
          {
              if (controllerContext.ControllerDescriptor == null)
                  GetControllerType();
      
              var actionSelector = new ApiControllerActionSelector();
              var descriptor = actionSelector.SelectAction(controllerContext);
      
              return descriptor.ActionName;
          }
      
          public Type GetControllerType()
          {
              var descriptor = controllerSelector.SelectController(request);
              controllerContext.ControllerDescriptor = descriptor;
              return descriptor.ControllerType;
          }
          #endregion
      }

      下面是路由測試:

      [TestFixture]
      public class RouteTests
      {
          #region Variables
          HttpConfiguration _config;
          #endregion
      
          #region Setup
          [SetUp]
          public void Setup()
          {
              _config = new HttpConfiguration();
              _config.Routes.MapHttpRoute(name: "DefaultWebAPI", routeTemplate: "api/{controller}/{id}", defaults: new { id = RouteParameter.Optional });
          }
          #endregion
      
          #region Helper methods
          public static string GetMethodName(Expression> expression)
          {
              var method = expression.Body as MethodCallExpression;
              if (method != null)
                  return method.Method.Name;
      
              throw new ArgumentException("Expression is wrong");
          }
          #endregion
      }

      測試一個請求api/articles/5到ArticleController的action GetArticle(int id)

      [Test]
      public void RouteShouldControllerGetArticleIsInvoked()
      {
          var request = new HttpRequestMessage(HttpMethod.Get, "http://www.chsakell.com/api/articles/5");
      
          var _actionSelector = new ControllerActionSelector(_config, request);
      
          Assert.That(typeof(ArticlesController), Is.EqualTo(_actionSelector.GetControllerType()));
          Assert.That(GetMethodName((ArticlesController c) => c.GetArticle(5)),
              Is.EqualTo(_actionSelector.GetActionName()));
      }

      我們用反射得到controller的action名稱,用同樣的方法來測試post提交的action

      [Test]
      public void RouteShouldPostArticleActionIsInvoked()
      {
          var request = new HttpRequestMessage(HttpMethod.Post, "http://www.chsakell.com/api/articles/");
      
          var _actionSelector = new ControllerActionSelector(_config, request);
      
          Assert.That(GetMethodName((ArticlesController c) =>
              c.PostArticle(new Article())), Is.EqualTo(_actionSelector.GetActionName()));
      }

      下面這個測試,路由會發(fā)生異常.

      [Test]
      public void RouteShouldInvalidRouteThrowException()
      {
          var request = new HttpRequestMessage(HttpMethod.Post, "http://www.chsakell.com/api/InvalidController/");
      
          var _actionSelector = new ControllerActionSelector(_config, request);
      
          Assert.Throws(() => _actionSelector.GetActionName());
      }

      結(jié)論

      我們看到了Web API棧很多方面的單元測試,例如: mocking 服務(wù)層,單元測試控制器,消息管道,過濾器,定制媒體類型和路由配置。

      嘗試在你的程序中總是寫單元測試,你不會后悔的。從里面會得到很多的好處,例如:在repository中一個簡單的修改可能破壞很多方面,如果寫一個合適的測試,則可能破壞你程序的問題會立即出現(xiàn).

      原文:chsakell's Blog


      當(dāng)前題目:ASP.NETWebAPI單元測試-單元測試
      當(dāng)前鏈接:http://ef60e0e.cn/article/gegioe.html
      99热在线精品一区二区三区_国产伦精品一区二区三区女破破_亚洲一区二区三区无码_精品国产欧美日韩另类一区
      1. <ul id="0c1fb"></ul>

        <noscript id="0c1fb"><video id="0c1fb"></video></noscript>
        <noscript id="0c1fb"><listing id="0c1fb"><thead id="0c1fb"></thead></listing></noscript>

        四子王旗| 同江市| 永安市| 铜梁县| 六枝特区| 巴彦县| 兴义市| 靖宇县| 灵川县| 紫云| 马鞍山市| 泸定县| 林周县| 建德市| 阿拉善盟| 谷城县| 抚顺市| 衢州市| 阳泉市| 美姑县| 成武县| 盘山县| 务川| 韩城市| 塘沽区| 肥西县| 政和县| 延寿县| 定结县| 嘉禾县| 新津县| 瑞昌市| 太仆寺旗| 大竹县| 郓城县| 北海市| 石景山区| 敦化市| 晋州市| 汕尾市| 临海市|