WebApi2官网学习记录---单元测试
如果没有对应的web api模板,首先使用nuget进行安装
例子1:
ProductController 是以硬编码的方式使用StoreAppContext类的实例,可以使用依赖注入模式,在外部指定上下文实例
public interface IStoreAppContext:IDisposable
{
DbSet<Product> Products { get; set; }
int SaveChanges();
void MarkAsModified(Product item);
} public class StoreAppContext : DbContext,IStoreAppContext
{
// You can add custom code to this file. Changes will not be overwritten.
//
// If you want Entity Framework to drop and regenerate your database
// automatically whenever you change your model schema, please use data migrations.
// For more information refer to the documentation:
// http://msdn.microsoft.com/en-us/data/jj591621.aspx public StoreAppContext() : base("name=StoreAppContext")
{
} public DbSet<Product> Products { get; set; } public void MarkAsModified(Product item)
{
Entry(item).State = EntityState.Modified;
}
} public class ProductsController : ApiController
{
private IStoreAppContext db = new StoreAppContext(); public ProductsController() { } public ProductsController(IStoreAppContext context)
{
db = context;
}
// GET: api/Products
public IQueryable<Product> GetProducts()
{
return db.Products;
} // GET: api/Products/5
[ResponseType(typeof(Product))]
public IHttpActionResult GetProduct(int id)
{
Product product = db.Products.Find(id);
if (product == null)
{
return NotFound();
} return Ok(product);
} // PUT: api/Products/5
[ResponseType(typeof(void))]
public IHttpActionResult PutProduct(int id, Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} if (id != product.Id)
{
return BadRequest();
} db.MarkAsModified(product); try
{
db.SaveChanges();
}
catch (DbUpdateConcurrencyException)
{
if (!ProductExists(id))
{
return NotFound();
}
else
{
throw;
}
} return StatusCode(HttpStatusCode.NoContent);
} // POST: api/Products
[ResponseType(typeof(Product))]
public IHttpActionResult PostProduct(Product product)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
} db.Products.Add(product);
db.SaveChanges(); return CreatedAtRoute("DefaultApi", new { id = product.Id }, product);
} // DELETE: api/Products/5
[ResponseType(typeof(Product))]
public IHttpActionResult DeleteProduct(int id)
{
Product product = db.Products.Find(id);
if (product == null)
{
return NotFound();
} db.Products.Remove(product);
db.SaveChanges(); return Ok(product);
} protected override void Dispose(bool disposing)
{
if (disposing)
{
db.Dispose();
}
base.Dispose(disposing);
} private bool ProductExists(int id)
{
return db.Products.Count(e => e.Id == id) > ;
}
}
单元测试代码:
public class TestDbSet<T>:DbSet<T>,IQueryable,IEnumerable<T>
where T:class
{
ObservableCollection<T> _data;
IQueryable _query; public TestDbSet()
{
_data = new ObservableCollection<T>();
_query = _data.AsQueryable();
} public override T Add(T item)
{
_data.Add(item);
return item;
} public override T Remove(T item)
{
_data.Remove(item);
return item;
} public override T Attach(T item)
{
_data.Add(item);
return item;
} public override T Create()
{
return Activator.CreateInstance<T>();
} public override TDerivedEntity Create<TDerivedEntity>()
{
return Activator.CreateInstance<TDerivedEntity>();
} public override ObservableCollection<T> Local
{
get { return new ObservableCollection<T>(_data); }
} Type IQueryable.ElementType
{
get { return _query.ElementType; }
} System.Linq.Expressions.Expression IQueryable.Expression
{
get { return _query.Expression; }
} IQueryProvider IQueryable.Provider
{
get { return _query.Provider; }
} System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
{
return _data.GetEnumerator();
} IEnumerator<T> IEnumerable<T>.GetEnumerator()
{
return _data.GetEnumerator();
}
} class TestProductDbSet:TestDbSet<Product>
{
public override Product Find(params object[] keyValues)
{
return this.SingleOrDefault(p=>p.Id==(int)keyValues.Single());
}
} class TestStoreAppContext : IStoreAppContext
{
public TestStoreAppContext()
{
this.Products = new TestProductDbSet();
} public System.Data.Entity.DbSet<Product> Products { get; set; } public int SaveChanges()
{
return ;
} public void MarkAsModified(Product item)
{ } public void Dispose()
{ }
} public class TestProductController
{
[TestMethod]
public void PostProduct_ShouldReturnSameProduct()
{
var controller = new ProductsController(new TestStoreAppContext());
var item = GetDemoProduct(); var result=controller.PostProduct(item) as CreatedAtRouteNegotiatedContentResult<Product>;
Assert.IsNotNull(result);
Assert.AreEqual(result.RouteName, "DefaultApi");
Assert.AreEqual(result.RouteValues["id"], result.Content.Id);
Assert.AreEqual(result.Content.Name, item.Name);
}
[TestMethod]
public void PutProduct_ShouldReturnStatusCode()
{
var controller = new ProductsController(new TestStoreAppContext()); var item = GetDemoProduct(); var result = controller.PutProduct(item.Id, item) as StatusCodeResult;
Assert.IsNotNull(result);
Assert.IsInstanceOfType(result, typeof(StatusCodeResult));
Assert.AreEqual(HttpStatusCode.NoContent, result.StatusCode);
} [TestMethod]
public void PutProduct_ShouldFail_WhenDifferentID()
{
var controller = new ProductsController(new TestStoreAppContext()); var badresult = controller.PutProduct(, GetDemoProduct());
Assert.IsInstanceOfType(badresult, typeof(BadRequestResult));
} [TestMethod]
public void GetProduct_ShouldReturnProductWithSameID()
{
var context = new TestStoreAppContext();
context.Products.Add(GetDemoProduct()); var controller = new ProductsController(context);
var result = controller.GetProduct() as OkNegotiatedContentResult<Product>; Assert.IsNotNull(result);
Assert.AreEqual(, result.Content.Id);
} [TestMethod]
public void GetProducts_ShouldReturnAllProducts()
{
var context = new TestStoreAppContext();
context.Products.Add(new Product { Id = , Name = "Demo1", Price = });
context.Products.Add(new Product { Id = , Name = "Demo2", Price = });
context.Products.Add(new Product { Id = , Name = "Demo3", Price = }); var controller = new ProductsController(context);
var result = controller.GetProducts() as TestProductDbSet; Assert.IsNotNull(result);
Assert.AreEqual(, result.Local.Count);
} [TestMethod]
public void DeleteProduct_ShouldReturnOK()
{
var context = new TestStoreAppContext();
var item = GetDemoProduct();
context.Products.Add(item); var controller = new ProductsController(context);
var result = controller.DeleteProduct() as OkNegotiatedContentResult<Product>; Assert.IsNotNull(result);
Assert.AreEqual(item.Id, result.Content.Id);
}
Product GetDemoProduct()
{
return new Product() { Id = , Name = "Demo name", Price = };
}
}
具体的代码参见:Mocking Entity Framework when Unit Testing ASP.NET Web API 2
WebApi2官网学习记录---单元测试的更多相关文章
- WebApi2官网学习记录---Cookie
Cookie的几个参数: Domain.Path.Expires.Max-Age 如果Expires与Max-Age都存在,Max-Age优先级高,如果都没有设置cookie会在会话结束后删除cook ...
- WebApi2官网学习记录---批量处理HTTP Message
原文:Batching Handler for ASP.NET Web API 自定义实现HttpMessageHandler public class BatchHandler : HttpMess ...
- WebApi2官网学习记录---Html Form Data
HTML Forms概述 <form action="api/values" method="post"> 默认的method是GET,如果使用GE ...
- WebApi2官网学习记录--HttpClient Message Handlers
在客户端,HttpClient使用message handle处理request.默认的handler是HttpClientHandler,用来发送请求和获取response从服务端.可以在clien ...
- WebApi2官网学习记录--HTTP Message Handlers
Message Handlers是一个接收HTTP Request返回HTTP Response的类,继承自HttpMessageHandler 通常,一些列的message handler被链接到一 ...
- WebApi2官网学习记录---Configuring
Configuration Settings WebAPI中的configuration settings定义在HttpConfiguration中.有一下成员: DependencyResolver ...
- WebApi2官网学习记录--- Authentication与Authorization
Authentication(认证) WebAPI中的认证既可以使用HttpModel也可以使用HTTP message handler,具体使用哪个可以参考一下依据: 一个HttpModel可以 ...
- WebApi2官网学习记录---Tracing
安装追踪用的包 Install-Package Microsoft.AspNet.WebApi.Tracing Update-Package Microsoft.AspNet.WebApi.WebHo ...
- WebApi2官网学习记录---异常处理
HttpResponseException 当WebAPI的控制器抛出一个未捕获的异常时,默认情况下,大多数异常被转为status code为500的http response即服务端错误. Http ...
随机推荐
- HTML5 Canvas图像放大、移动实例1
1.前台代码 <canvas id="canvasOne" class="myCanvas" width="500" height=& ...
- (转)js 正则表达式之test函数讲解
该方法的返回值是布尔值,通过该值可以匹配字符串中是否存在于正则表达式相匹配的结果,如果有匹配内容,返回ture,如果没有匹配内容返回false,该方法常用于判断用户输入数据的合法性,比如检验Email ...
- MVC第一节 配置
1.View中的页面设置为起始页后导致404找不到文件. 解决方案:右键属性,把特定页置为空. 2.新建的MVC项目会把系统默认的浏览器作为浏览方式,如果想要改变的话.可以在项目中新建一个webFor ...
- IPointCollection,ISegmentCollection和IGeometryCollection
Engine 提供了三个主要的几何图形集合接口用于对几何对象的操作,分别是 IPointCollection,ISegmentCollection 和 IGeometryCollection,这些接口 ...
- [c#]控制台进度条的示例
看到[vb.net]控制台进度条的示例 感觉很好玩,翻译成C#版. using System; using System.Collections.Generic; using System.Linq; ...
- Collection使用方法
package cn.stat.p3.conection.demo; import java.util.ArrayList; import java.util.Collection; import j ...
- Linux_access the file or directory which start with "-"
cd -- filename/dirName [ccmobil@vm-a65a-fc19 wstemp]$ cd -/ -bash: cd: -: invalid option cd: usage: ...
- git强制更新
1.下载远程的库的内容 git fetch --all 2.把HEAD指向刚刚下载的最新的版本 git reset --hard origin/master
- Unicode字符集下CString与char *相互转换
经常遇到CString转换char*时只返回第一个字符.原因是因为在Unicode字符集下CString会以Unicode的形式来保存数据,强制类型转换只会返回第一个字符.所以直接转换在基于MBCS的 ...
- 禁用与启用Button点击
//启用查询按钮 btnFpSelect.setClickable(true); //禁用查询按钮 btnFpSelect.setClickable(false);