项目的开发过程中,在数据访问层,里面的CRUD函数已经全部测试通过。现在在逻辑服务层有一个Manager类,Manager里也有CRUD函数,调用数据访问层的CRUD函数,而没有其他逻辑。在我们测试Manager的CRUD的函数时,是否真的也要去访问数据库呢?答案是否定的。
我们只要测试Manager里的CRUD函数是否调用了数据访问层里面的函数即可!
这里我们可以用Moq来测试。要用到Moq插件。下载地址在此:点击打开链接
因为Moq只对虚函数或者抽象函数有用,所以要为数据访问层里的那个类添加一个接口。形如
public interface IRepository
{
Test AddEntity(Test t);
}
public class TestRepository : IRepository
{
private Test TestEntity;
public TestRepository()
{
this.TestEntity = new Test();
}
public Test AddEntity(Test t)
{
if (t == null)
{
return null;
}
TripEntities te = new TripEntities();
DbSet testSet = te.Set<Test>();
testSet.Add(t);
te.SaveChanges();
return t;
}
}
这里只贴出AddEntity有代码,其它CRUD函数不贴出。
现在我们来看Manager类的相关代码
public class Manager
{
private IRepository repository;
public Manager()
: this(new TestRepository())
{
}
public Manager(IRepository tr)
{
this.repository = tr;
}
public Test AddEntity(Test t)
{
if (t == null)
{
return null;
}
return this.repository.AddEntity(t);
}
}
注意到这里的Manager有两个构造函数。带参数的构造函数用到的是 依赖注入中的构造注入方法,通过构造函数的参数为可服务对象指定服务。
现在开始写测试函数了。可以用vs自带的测试工具也可以用Nunit,我这里的是Nunit,下载地址:点击打开链接。 且来看代码:
using Moq;
using NUnit.Framework;
[TestFixture]
public class UnitTestManager
{
[Test]
public void TestAddEntity()
{
var repository = new Mock<IRepository>();
Test expected = new Test { SID = 3, Name = "hell", Notes = "go", };
repository.Setup(a => a.AddEntity(It.IsAny<Test>()))
.Returns(expected).Verifiable();
Manager m = new Manager(repository.Object);
Test t = new Test();
var actual = m.AddEntity(t);
repository.Verify(a => a.AddEntity(It.IsAny<Test>()), Times.AtLeastOnce(), "至少一次");
Assert.AreEqual(expected.SID, actual.SID);
Assert.AreEqual(expected.Name, actual.Name);
Assert.AreEqual(expected.Notes, actual.Notes);
}
}
现在我们能测试到Manager的AddEntity函数至少调用了一次Repository里面的函数。当然返回的actual并不是真正访问了数据库而是我们的模拟数据,在这里仍然测试它的值,是为了保证Manager的AddEntity函数没有出异常。