Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/262.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单元测试-数据库数据_C#_Sql Server_Unit Testing_Stored Procedures - Fatal编程技术网

C# 单元测试-数据库数据

C# 单元测试-数据库数据,c#,sql-server,unit-testing,stored-procedures,C#,Sql Server,Unit Testing,Stored Procedures,我尝试为一些具有存储过程的方法创建单元测试。以下是我的问题 如何对使用大量存储过程的项目进行单元测试 从数据库获取数据以进行验证 如果我必须从单元测试调用这些方法,我实际上 不打数据库电话…值得吗 如果我必须使用模拟数据,如何从 本地数据库 如何模拟存储过程调用以使用模拟数据 您看到的是集成测试,而不是单元测试。集成测试依赖于外部系统(datetime、数据库、文件系统、networkservice等),而单元测试的范围仅限于一个单元(一个或多个类中的一个或多个方法) 这里要认识到的第一件

我尝试为一些具有存储过程的方法创建单元测试。以下是我的问题

  • 如何对使用大量存储过程的项目进行单元测试 从数据库获取数据以进行验证

    • 如果我必须从单元测试调用这些方法,我实际上 不打数据库电话…值得吗

    • 如果我必须使用模拟数据,如何从 本地数据库

    • 如何模拟存储过程调用以使用模拟数据


您看到的是集成测试,而不是单元测试。集成测试依赖于外部系统(datetime、数据库、文件系统、networkservice等),而单元测试的范围仅限于一个单元(一个或多个类中的一个或多个方法)

这里要认识到的第一件事是,为了进行集成测试,您将依赖于外部系统。您永远不希望针对生产环境进行测试,并且希望保持对测试数据的控制

因此,您应该创建一个与现有数据库完全相同的数据库,但删除所有数据并使用模拟数据。这确保您的测试在整个更改过程中保持一致,因此可以信赖。
您还应该记住保持您的测试数据库在功能上等同于您的实时数据库,以避免落后和过时的测试

这里的关键是:抽象数据源层。如果您将所有的数据库调用放在一个接口后面,您可以简单地模拟/存根这个接口并从那里提供测试数据

你的工作单元应该切中要害,测试方法应该做的一件事(单一责任原则)。
如果方法的目标是操作数据库中的数据,则模拟数据源并对操作进行单元测试。
如果方法的目标是调用数据库中的存储过程,则使用集成测试为过程输入提供数据,并针对其输出进行断言

这一原则的一个简单示例:

interface DataSource {
    List<String> GetData();
}

class Manipulator {
    private DataSource _source;

    public Manipulator() { }

    public Manipulator(DataSource d) { _source = d; }

    public void ManipulateData() {
        var data = _source.GetData();

        // Do something with the data
    }
}
接口数据源{
List GetData();
}
类操纵器{
私有数据源_源;
公共操纵器(){}
公共操纵器(数据源d){u source=d;}
公共空间数据(){
var data=_source.GetData();
//对数据做点什么
}
}
此示例利用构造函数注入(查看依赖项注入和IoC容器的概念!)

现在回答您的问题:

如果我必须从我的单元测试中调用这些方法,我实际上没有进行任何数据库调用…值得吗

是的,否则您没有集成测试。因为您有一个单独的测试数据库,所以这不会干扰您的生产环境

如果必须使用模拟数据,如何从本地数据库获取数据副本

老实说,我不太确定您在这里要问什么,但我认为通过一个测试数据库的想法可以解决这个问题

如何模拟存储过程调用以使用模拟数据


你没有。通过使用测试数据调用实际存储过程,并根据预期断言结果,可以使用实际存储过程。如果它们工作,那么就到此为止,如果它们没有返回正确的结果,那么您就知道出了问题。

您需要定义一个包含所有数据访问方法的
接口。您已经有了一个包含这些方法的类,所以您可以在VisualStudio中通过右键单击数据访问类中的空白区域并选择refactor然后Extract Interface来重构它。因此,现在您有了一个
接口
,您需要添加一个实现该
接口
的模拟数据访问类


在执行此操作时,您的模拟数据访问类不需要了解任何存储过程,只要它返回一些由
接口指定的正确类型的数据。最后一部分是在使用应用程序时传递实际数据访问类的实例,为了进行测试,请传递模拟数据访问类的实例。

调用存储过程的哪一部分需要测试?您正在编写自己的SQL类吗?(对于常规应用程序,您只需模拟数据持久性层,不必担心单元测试中的DB调用…)为了验证字段,它会进行两次DB调用,并根据返回的数据对这些字段进行两次验证,并返回true或false。在这种情况下,你会如何嘲笑?模拟数据持久层是什么意思?请给我硼。非常感谢您的回复!Jeroen Vannevel有非常详细的答案(+1)。看起来您确实不需要对这种情况进行单元测试。非常感谢您的详细解释!我们有相同数据库的不同副本…比如说100。数据在某些情况下可能不同,但在某些情况下相同。在这种情况下,什么是更好的方法?为什么有100个数据库?它们是同一个数据库,功能上只是不同的数据,还是数据库完全不同?是的!在大多数情况下,对于不同的数据,它都是相同的模式…出于数据保护和其他原因,它被单独维护。谢谢那么您只需要一个测试数据库。您希望测试数据库中的功能(存储过程),而不是数据本身。现在您将有101个数据库:100个包含生产数据,1个包含测试数据,您可以在其中执行测试。