繁体   English   中英

与数据库通信的单元测试类

[英]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类时将其注入。 为了进行单元测试,请在单元测试中模拟依赖项,以确保它以预期的方式调用已定义的依赖项合同。

通常,这意味着:

  • 定义依赖项的接口,即IMyData
  • 构造函数签名应使用接口类型,而不是具体类型。

最终结果是,您的代码将进行如下转换:

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM