简体   繁体   English

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

[英]Unit Testing class which communicates with a database

Ok Lets assume i have a class which controls my data layer and a class which performs the work. 好的,假设我有一个控制我的数据层的类和一个执行工作的类。

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;
    }
}

How can i test my DoWork method with a unit test without accessing the database. 如何在不访问数据库的情况下使用单元测试来测试DoWork方法。

[TestMethod()]
public void TestMyWork()
{
    MyWork work = new MyWork();
    int result = work.DoWork();
    Assert.AreEqual(1, result);
}

Make the MyData class a dependency parameter and inject it during construction of your MyWork class. 使MyData类成为依赖项参数,并在构造MyWork类时将其注入。 For unit testing purposes, mock the dependency in your unit test to ensure that it is calling the defined dependency's contract in an expected manner. 为了进行单元测试,请在单元测试中模拟依赖项,以确保它以预期的方式调用已定义的依赖项合同。

Typically this means: 通常,这意味着:

  • Defining an interface for the dependency ie IMyData 定义依赖项的接口,即IMyData
  • The constructor signature should expect the interface type rather than the concrete type. 构造函数签名应使用接口类型,而不是具体类型。

As a final result, your code would be transformed as follows: 最终结果是,您的代码将进行如下转换:

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;
    }
}

As a step further, you should check out the SOLID design principles as this type of design demonstrates why they exist. 进一步,您应该检查SOLID设计原则,因为这种类型的设计说明了它们为什么存在。

More on Wikipedia: SOLID (OO design) 有关Wikipedia的更多信息:SOLID(面向对象设计)

Edit: 编辑:

Your unit test would then look something like (assuming you're using the Moq mocking framework): 然后,您的单元测试将类似于(假设您使用的是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);
}

..but in the real world you would more than likely instantiate MyWork with a real MyData instance as follows (unless you're using a Dependency Injection framework such as MEF or Unity): ..但是在现实世界中,您很有可能按照如下所示使用真实的MyData实例实例化MyWork (除非您使用的是Dependency Injection框架,例如MEF或Unity):

var myWork = new MyWork(new MyData());

First, follow @toadflakz advice and inject MyData to MyWork 's constructor. 首先,遵循@toadflakz建议并将MyData注入MyWork的构造函数中。

Then, use some ORM to map the data from the db to objects. 然后,使用一些ORM将数据从db映射到对象。 Don't use DataTable . 不要使用DataTable

To make DoWork easier to test, consider refactoring it into a pure function : 为了使DoWork易于测试,请考虑将其重构为一个纯函数

public int DoWork(DataTable dt)
{
    // make some complex calculations on dt
}

This way the result of DoWork depends only on the input parameter, which makes it very easy to test. 这样, DoWork的结果仅取决于输入参数,这使得测试非常容易。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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