Ok让我们假设我有一个控制我的数据层的类和一个执行工作的类。
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);
}
答案 0 :(得分:5)
使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 (OO design)
修改强>
您的单元测试看起来就像(假设您正在使用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);
}
..但在现实世界中,您很可能使用真实MyWork
实例实例化MyData
,如下所示(除非您使用的是依赖注入框架,如MEF或Unity): / p>
var myWork = new MyWork(new MyData());
答案 1 :(得分:1)
首先,关注@toadflakz建议并将MyData
注入MyWork
的构造函数。
然后,使用一些ORM将数据从db映射到对象。请勿使用DataTable
。
要使DoWork
更容易测试,请考虑将其重构为pure function:
public int DoWork(DataTable dt)
{
// make some complex calculations on dt
}
这样DoWork
的结果仅取决于输入参数,这使得测试变得非常容易。