博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
MVC单元测试,使用Repository模式、Ninject、Moq
阅读量:6080 次
发布时间:2019-06-20

本文共 8331 字,大约阅读时间需要 27 分钟。

本篇使用Repository设计MVC项目,使用Ninject作为DI容器,借助Moq进行单元测试。

 

  模型和EF上下文

模型很简单:

public class Foo    {        public int Id { get; set; }        public string Name { get; set; }    }

EF上下文为:

using System.Data.Entity;namespace MvcApplication1.Models{    public class FooBarContext : DbContext    {        public DbSet
Foos { get; set; } }}

 

  Repository相关

为了避免在IXXXRepository中有关增删改查等的重复代码,有必要创建一个所有IXXXRepository的基接口:

using System;using System.Linq;using System.Linq.Expressions;namespace MvcApplication1.Repository{    public interface IBaseRepository
where T : class { IQueryable
GetAll(); IQueryable
FindBy(Expression
> predicate); void Add(T entity); void Edit(T entity); void Delete(T entity); void Save(); }}

IFooRepository,也可以有自己的接口方法:

using MvcApplication1.Models;namespace MvcApplication1.Repository{    public interface IFooRepository : IBaseRepository
{ Foo GetSingle(int fooId); }}

BaseRepository是一个抽象类,提供了所有XXXRepository的泛型基类实现,并实现 IBaseRepository接口:

using System.Data.Entity;using System.Linq;namespace MvcApplication1.Repository{    public abstract class BaseRepository
: IBaseRepository
where T : class where C : DbContext,new() { private C _db = new C(); public C Db { get { return _db; } set { _db = value; } } public System.Linq.IQueryable
GetAll() { IQueryable
query = _db.Set
(); return query; } public System.Linq.IQueryable
FindBy(System.Linq.Expressions.Expression
> predicate) { IQueryable
query = _db.Set
().Where(predicate); return query; } public void Add(T entity) { _db.Set
().Add(entity); } public void Edit(T entity) { _db.Entry(entity).State = EntityState.Modified; } public void Delete(T entity) { _db.Set
().Remove(entity); } public void Save() { _db.SaveChanges(); } }}

FooRepository不仅派生于BaseRepository<FooBarContext, Foo>,还需要实现IFooRepository约定的接口方法:

using System.Linq;using MvcApplication1.Models;namespace MvcApplication1.Repository{    public class FooRepository : BaseRepository
,IFooRepository { public Foo GetSingle(int fooId) { var query = GetAll().FirstOrDefault(x => x.Id == fooId); return query; } }}

 

  Ninject控制器工厂

通过GuGet安装Ninjct,创建Ninject控制器工厂:

using System.Web.Mvc;using MvcApplication1.Repository;using Ninject;namespace MvcApplication1.Extension{    public class NinjectControllerFactory : DefaultControllerFactory    {        private IKernel ninjectKernel;        public NinjectControllerFactory()        {            ninjectKernel = new StandardKernel();        }        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, System.Type controllerType)        {            return controllerType == null ? null : (IController) ninjectKernel.Get(controllerType);        }        private void AddBindings()        {            ninjectKernel.Bind
().To
(); ninjectKernel.Bind
().To
(); } }}

并在全局注册:

protected void Application_Start()        {            ......            ControllerBuilder.Current.SetControllerFactory(new NinjectControllerFactory());        }

 

  创建FooController,包含增删改查

using System;using System.Web.Mvc;using MvcApplication1.Models;using MvcApplication1.Repository;namespace MvcApplication1.Controllers{    public class FooController : Controller    {        private readonly IFooRepository _fooRepository;        public FooController(IFooRepository fooRepository)        {            _fooRepository = fooRepository;        }        public ViewResult Index()        {            var model = _fooRepository.GetAll();            return View(model);        }        public ActionResult Details(int id)        {            var model = _fooRepository.GetSingle(id);            if (model == null)            {                return HttpNotFound();            }            return View(model);        }        public ActionResult Edit(int id)        {            var model = _fooRepository.GetSingle(id);            if (model == null)            {                return HttpNotFound();            }            return View(model);        }        [ActionName("Edit"), HttpPost]        public ActionResult Eidt_Post(Foo foo)        {            if (ModelState.IsValid)            {                try                {                    _fooRepository.Edit(foo);                    _fooRepository.Save();                    return RedirectToAction("Details", new { id = foo.Id });                }                catch (Exception ex)                {                   ModelState.AddModelError(string.Empty, "出错了:" + ex.Message);                }            }            return View(foo);        }        public ActionResult Create()        {            return View();        }        [ActionName("Create"), HttpPost]        public ActionResult Create_Post(Foo foo)        {            if (ModelState.IsValid)            {                try                {                    _fooRepository.Add(foo);                    _fooRepository.Save();                    return RedirectToAction("Details", new {id = foo.Id});                }                catch (Exception ex)                {                   ModelState.AddModelError(string.Empty, "出错了:"+ex.Message);                }            }            return View(foo);        }        public ActionResult Delete(int id)        {            var model = _fooRepository.GetSingle(id);            if (model == null)            {                return HttpNotFound();            }            return View(model);        }        [ActionName("Delete"),HttpPost]        public ActionResult Delete_Post(int id)        {            var model = _fooRepository.GetSingle(id);            if (model == null)            {                return HttpNotFound();            }            _fooRepository.Delete(model);            _fooRepository.Save();            return RedirectToAction("Index");        }    }}

 

  单元测试

通过NuGet安装Moq,借助Moq来模拟接口方法的返回值。

→初始化

private IFooRepository fooRepository;        [TestInitialize]        public void Initialize()        {            Mock
mock = new Mock
(); mock.Setup(m => m.GetAll()).Returns(new Foo[] { new Foo(){Id = 1, Name = "Fake Foo 1"}, new Foo(){Id = 2, Name = "Fake Foo 2"}, new Foo(){Id = 3, Name = "Fake Foo 3"}, new Foo(){Id = 4, Name = "Fake Foo 4"} }.AsQueryable()); mock.Setup(m => m.GetSingle(It.Is
(i =>i == 1 || i == 2 || i == 3 || i == 4))).Returns
(r => new Foo { Id = r, Name = string.Format("Fake Foo {0}", r) }); fooRepository = mock.Object; }

 

→测试返回类型

[TestMethod]        public void is_index_return_model_type_of_iqueryable_foo()        {            //Arragne            FooController fooController = new FooController(fooRepository);            //Act            var indexModel = fooController.Index().Model;            //Assert            Assert.IsInstanceOfType(indexModel, typeof(IQueryable
)); } [TestMethod] public void is_details_returns_type_of_ViewResult() { //Arrange FooController fooController = new FooController(fooRepository); //Act var detailsResult = fooController.Details(1); //Assert Assert.IsInstanceOfType(detailsResult, typeof(ViewResult)); } [TestMethod] public void is_details_returns_type_of_HttpNotFoundResult() { //Arrange FooController fooController = new FooController(fooRepository); //Act var detailsResult = fooController.Details(5); //Assert Assert.IsInstanceOfType(detailsResult, typeof(HttpNotFoundResult)); }

→测试返回集合类型Model的数量  

 

结果:

 

参考资料:               

转载地址:http://pnhgx.baihongyu.com/

你可能感兴趣的文章
微软发布Windows 8标志:彰显创新回归本源(图)
查看>>
测试常用辅助工具汇总
查看>>
mysql 高性能压力测试(总结了好久)
查看>>
接口测试是什么&接口测试文档规范
查看>>
快速搭建LAMP环境
查看>>
异步编程需要“意识”
查看>>
英语语法时态
查看>>
linux双网卡绑定
查看>>
VR+房產
查看>>
版本管理 GitLab 的安装及管理 (CentOS 7)
查看>>
以太网到以太网的本地交换
查看>>
Windows Server 2012之活动目录域服务部署
查看>>
ORACLE Bug 4431215 引发的血案—处理篇
查看>>
js切割字符串问题
查看>>
微信语音遥控Windows Azure云虚拟机
查看>>
DNS主机记录也能用*
查看>>
监视DNS服务器工作是否正常
查看>>
理解并取证:动态路由协议RIP的工作原理
查看>>
你也可以拥有F5
查看>>
Windows Server 2012 Release Candidate (RC发行预览版) Datacenter抢鲜看
查看>>