[英]Unit Testing class which communicates with a database
好的,假设我有一个控制我的数据层的类和一个执行工作的类。
class MyData
{
public DataTable GetMyData()
{
return Query.MyDataBase.ResultDT();
}
}
class MyWork
{
public int DoWork()
{
MyData Data = new MyData();
DataTable DT = Data.GetMyData();
return DT.Rows.Count;
}
}
如何在不访问数据库的情况下使用单元测试来测试DoWork方法。
[TestMethod()]
public void TestMyWork()
{
MyWork work = new MyWork();
int result = work.DoWork();
Assert.AreEqual(1, result);
}
使MyData
类成为依赖项参数,并在构造MyWork
类时将其注入。 为了进行单元测试,请在单元测试中模拟依赖项,以确保它以预期的方式调用已定义的依赖项合同。
通常,这意味着:
最终结果是,您的代码将进行如下转换:
interface IMyData
{
DataTable GetMyData();
}
class MyData : IMyData
{
public DataTable GetMyData()
{
return Query.MyDataBase.ResultDT();
}
}
class MyWork
{
private IMyData _myData;
public MyWork(IMyData myData)
{
_myData = myData;
}
public int DoWork()
{
DataTable DT = _myData.GetMyData();
return DT.Rows.Count;
}
}
进一步,您应该检查SOLID设计原则,因为这种类型的设计说明了它们为什么存在。
有关Wikipedia的更多信息:SOLID(面向对象设计)
编辑:
然后,您的单元测试将类似于(假设您使用的是Moq模拟框架):
[TestMethod()]
public void TestMyWork()
{
var mockMyData = Mock<IMyData>();
mockMyData.Setup(x => x.GetMyData()).Returns(new DataTable());
MyWork work = new MyWork(mockMyData);
int result = work.DoWork();
Assert.AreEqual(1, result);
}
..但是在现实世界中,您很有可能按照如下所示使用真实的MyData
实例实例化MyWork
(除非您使用的是Dependency Injection框架,例如MEF或Unity):
var myWork = new MyWork(new MyData());
首先,遵循@toadflakz建议并将MyData
注入MyWork
的构造函数中。
然后,使用一些ORM将数据从db映射到对象。 不要使用DataTable
。
为了使DoWork
易于测试,请考虑将其重构为一个纯函数 :
public int DoWork(DataTable dt)
{
// make some complex calculations on dt
}
这样, DoWork
的结果仅取决于输入参数,这使得测试非常容易。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.