注意:单元测试不要包含数据库操作,包含数据库操作的一般成为集成测试。
namespace AspNetMVCEssential.Tests.Controllers
{
[TestClass]
public class HomeControllerTest
{
[TestMethod]
public void Index()
{
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.Index() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
[TestMethod]
public void About()
{
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.About() as ViewResult;
// Assert
Assert.AreEqual("Your application description page.", result.ViewBag.Message);
}
[TestMethod]
public void Contact()
{
// Arrange
HomeController controller = new HomeController();
// Act
ViewResult result = controller.Contact() as ViewResult;
// Assert
Assert.IsNotNull(result);
}
}
}
选定菜单“测试”->“运行”->运行所有测试或者未成功的测试。
可以在“测试”->“窗口”->“测试资源管理器”中对测试进行管理。
Mock测试就是在测试过程中,对于某些不容易构造或者不容易获取的对象,用一个虚拟的对象来创建以便测试的测试方法。
我们要对TransactionController.cs
进行测试,直接操作数据库不行,怎么办呢?我们可以使用虚拟的接口来进行测试。这需要我们更改一些代码.
TransactionController.cs
更改db为IApplicationDbContext
类型,并且添加构造方法:
private IApplicationDbContext db;
//实际使用
public TransactionController()
{
db = new ApplicationDbContext();
}
//生成使用
public TransactionController(IApplicationDbContext dbContext)
{
db = dbContext;
}
public interface IApplication
{
IDbSet<CheckingAccount> CheckingAccounts{get;set;}
IDbSet<Transaction> Transactions{get; set;}
public int SaveChanges();
}
让实际的ApplicationDbContext实现IApplicationDbContext。
另外创建一个假的FakeApplicationDbContext实现IApplicationDbContext
public class FakeApplicationDbContext:IApplicationDbContext
{
IDbSet<CheckingAccount> CheckingAccounts{get;set;}
IDbSet<Transaction> Transactions{get; set;}
public int SaveChanges(){return 0}
}
再创建一个FakeDbSet
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace EntityExtensions {
public class FakeDbSet<T> : System.Data.Entity.IDbSet<T> where T : class {
private readonly List<T> list = new List<T>();
public FakeDbSet() {
list = new List<T>();
}
public FakeDbSet(IEnumerable<T> contents) {
this.list = contents.ToList();
}
#region IDbSet<T> Members
public T Add(T entity) {
this.list.Add(entity);
return entity;
}
public T Attach(T entity) {
this.list.Add(entity);
return entity;
}
public TDerivedEntity Create<TDerivedEntity>() where TDerivedEntity : class, T {
throw new NotImplementedException();
}
public T Create() {
throw new NotImplementedException();
}
public T Find(params object[] keyValues) {
throw new NotImplementedException();
}
public System.Collections.ObjectModel.ObservableCollection<T> Local {
get {
throw new NotImplementedException();
}
}
public T Remove(T entity) {
this.list.Remove(entity);
return entity;
}
#endregion
#region IEnumerable<T> Members
public IEnumerator<T> GetEnumerator() {
return this.list.GetEnumerator();
}
#endregion
#region IEnumerable Members
System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator() {
return this.list.GetEnumerator();
}
#endregion
#region IQueryable Members
public Type ElementType {
get { return this.list.AsQueryable().ElementType; }
}
public System.Linq.Expressions.Expression Expression {
get { return this.list.AsQueryable().Expression; }
}
public IQueryProvider Provider {
get { return this.list.AsQueryable().Provider; }
}
#endregion
}
}
另外一种方法是使用
Install-Package FakeDbSet
创建失败的测试
用最简单的方法实现
优化
注意,测试应该也引用EF。