现在Asp.net webapi 运用的越来越多,其单元而是也越来越重要。一般软件开发都是多层结构,上层调用下层的接口,而各层的实现人员不同,一般大家都只写自己对应单元测试。对下层的依赖我们通过IOC来做。首先看我们的Controller定义及实现
public class ArticlesController : ApiController { private IArticleService _articleService; public ArticlesController(IArticleService articleService) { _articleService = articleService; } // GET: api/Articles public IEnumerable<Article> GetArticles() { return _articleService.GetArticles(); } // GET: api/Articles/5 [ResponseType(typeof(Article))] public IHttpActionResult GetArticle(int id) { Article article = _articleService.GetArticle(id); if (article == null) { return NotFound(); } return Ok(article); } // PUT: api/Articles/5 [ResponseType(typeof(void))] public IHttpActionResult PutArticle(int id, Article article) { if (!ModelState.IsValid) { return BadRequest(ModelState); } if (id != article.ID) { return BadRequest(); } try { _articleService.UpdateArticle(article); } catch (DbUpdateConcurrencyException) { if (!ArticleExists(id)) { return NotFound(); } else { throw; } } return StatusCode(HttpStatusCode.NoContent); } // POST: api/Articles [ResponseType(typeof(Article))] public IHttpActionResult PostArticle(Article article) { if (!ModelState.IsValid) { return BadRequest(ModelState); } _articleService.CreateArticle(article); return CreatedAtRoute("DefaultApi", new { id = article.ID }, article); } // DELETE: api/Articles/5 [ResponseType(typeof(Article))] public IHttpActionResult DeleteArticle(int id) { Article article = _articleService.GetArticle(id); if (article == null) { return NotFound(); } _articleService.DeleteArticle(article); return Ok(article); } private bool ArticleExists(int id) { return _articleService.GetArticle(id) != null; } } |
首先构造函数 需要IArticleService实例,在Controller的action中将需要用到该service。【请千万不要告诉我说这里的controller非常简单,不需要做单元测试!在实际项目中有人为了不做Controller的单元测试,把里面的逻辑全部提取出来放在Helper里面,然后对Helper来做单元测试】
IOC的实现:
我这里用的是Unity, 所以首先需要安装Install-Package Unity.WebApi.5.1
public class WebApiApplication : System.Web.HttpApplication { protected void Application_Start() { GlobalConfiguration.Configure(WebApiConfig.Register); //Install-Package Unity.WebApi.5.1 IUnityContainer container = new UnityContainer() .RegisterType<IArticleService, ArticleService>() .RegisterType<IBlogService, BlogService>(); //GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(container); GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), new UnityHttpControllerActivator(container)); } } public class UnityHttpControllerActivator : IHttpControllerActivator { public IUnityContainer UnityContainer { get; private set; } public UnityHttpControllerActivator(IUnityContainer unityContainer) { this.UnityContainer = unityContainer; } public IHttpController Create(HttpRequestMessage request, HttpControllerDescriptor controllerDescriptor, Type controllerType) { return (IHttpController)this.UnityContainer.Resolve(controllerType); } } |
一般我们的controller都只用DependencyResolver和IHttpControllerActivator 来实现控制反转。
单元测试我一般用Moq 和nunit ,所以需要 Install-Package Moq 和 Install-Package NUnit