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 ...
随机推荐
- inline-block容器的高度撑开位置
block的高度是从最上面撑开的 那么inline-block呢? 直接上代码 <!doctype html> <html> <head> <meta cha ...
- php echo字符串的连接格式
echo "<td align=\"center\"><img src=\""; 1. \" \" 2. ...
- 网站的优化----首页优化---app调取服务端数据
高并发经常会发生在有大活跃用户量来访问网站的某个点,例如用户高聚集的业务场景中,如:抢购,促销等.为了让用户流畅的访问网站,来根据自己的业务设计适合系统的处理方案. //对于APP网站首页数据,通常是 ...
- 用java pyhont通过HTTP协议传输文件流
// 代码网上抄的 忘记链接了 抱歉哈package upload; import java.io.BufferedReader; import java.io.DataOutputStream; i ...
- A*八数码
帮同学写的八数码,启发式搜索 创建两个表open,close,分别用的stl中的优先队列priority_queue和map,好久没写过代码了,bug调了半天 #include <iostrea ...
- git强制更新
1.下载远程的库的内容 git fetch --all 2.把HEAD指向刚刚下载的最新的版本 git reset --hard origin/master
- 一定要学会OutputDebugString,方便源码级调试
省得到处自己print,麻烦的要死...
- Qt信号和槽的个人总结
1.connect connect(sender,SIGNAL(signal()),receiver,SLOT(slot())); 这里用到了两个宏:SIGNAL() 和SLOT():通过connec ...
- Linq to BBJECT之非延时标准查询操作符
非延时标准查询操作符是指不具备延时查询特性的标准查询操作符,这些操作符一般用于辅助延时标准查询操作符使用. 1.ToArray操作符 ToArray操作符用于将一个输入序列转换成一个数组. 方法原型: ...
- linq 跨库查询
可以用多个DBContext,例如有DBContext1和DBContext2,但是不能将两个DBContext用在同一个查询中,可以分开,先用一个查出结果集1,再在第二个查询中使用结果集1就可以了