Asp.net mvc 如何实现/构建/创建';内存数据库';对于我的单元测试
我在不久前开始了单元测试,结果证明我做了比单元测试更多的回归测试,因为我还包括了我的数据库层,因此每次都要访问数据库 因此,实现了Unity以注入一个伪数据库层,但我当然想存储一些数据,主要观点是:“创建内存中的数据库” 但这是什么/我如何实现 主要的问题是:我认为我必须伪造数据库层,但这不是让我自己创建一个“简单数据库”吗?或者:我如何保持它的简单,而不只是为了单元测试而重建Sql Server:) 在这个问题的最后,我将解释一下我刚刚开始的项目的情况,我想知道这是否是一条路要走 米歇尔 我在这个客户端看到的当前情况是,testdata包含在XML文件中,并且有一个“伪”数据库层将所有XML文件连接在一起。 对于真实的数据库,我们使用实体框架,这非常简单。 现在,在“假”层,我创建了各种类型的类来加载、保存、持久化数据。 这听起来很奇怪,在假层中有这么多的工作,而在真实层中却很少 我希望这一切都有意义:) 编辑:Asp.net mvc 如何实现/构建/创建';内存数据库';对于我的单元测试,asp.net-mvc,database,unit-testing,Asp.net Mvc,Database,Unit Testing,我在不久前开始了单元测试,结果证明我做了比单元测试更多的回归测试,因为我还包括了我的数据库层,因此每次都要访问数据库 因此,实现了Unity以注入一个伪数据库层,但我当然想存储一些数据,主要观点是:“创建内存中的数据库” 但这是什么/我如何实现 主要的问题是:我认为我必须伪造数据库层,但这不是让我自己创建一个“简单数据库”吗?或者:我如何保持它的简单,而不只是为了单元测试而重建Sql Server:) 在这个问题的最后,我将解释一下我刚刚开始的项目的情况,我想知道这是否是一条路要走 米歇尔 我在
所以我知道我必须为我的单元测试创建一个单独的数据库层,但是我如何实现它呢?我在单元测试中使用的是假的DB我一直在内存中使用Sqlite进行单元测试,它非常有用为什么不使用模拟框架(比如moq或rhino模拟)?如果通过接口访问数据,则可以模拟该接口,并在每次测试中指定要返回的内容。另一种方法是使用单独的环境进行测试,使用“真实”数据库,在为生产环境编写代码之前进行测试。为数据访问层定义一个接口,并(至少)有两种实现:
- 真正的数据库提供程序,它将依次在SQL数据库上运行查询,等等
- 内存中的测试提供程序,可以在每个单元测试中预先填充测试数据
对于复杂的更新也是如此。事务支持对于真正的数据库实现是可能的。我不确定构建一个能够提供适当事务支持的内存数据库有多容易。要测试它,您需要“打开”多个到同一数据集的“连接”,并且在提交事务时只对该共享数据集应用更新。uhhh。。。。。。如果将所有测试数据存储在XML文件中。您刚刚将一个数据库更改为另一个数据库。这不是内存中的数据库。在PHP中,您可以使用如下内容
class MemoryProductDB {
private $products;
function MemoryProductDB() {
$this->products = array();
}
public function find($index) {
return $this->products[$index];
}
public function save($product) {
$this->products[$product['index']] = $product;
}
}
您注意到我的所有数据都存储在内存数组中,并从内存数组中检索。这是一个简单的内存数据库
IMHO,如果您使用XML存储测试数据,那么您实际上没有有效地断开依赖关系与模型和数据库的连接。无论您的业务规则有多复杂,当它们触及数据库时,它们真正做的只是CRUD(创建、检索、更新和删除)功能
如果您在模型中处理的是数据库中的多个对象,那么可能需要将所有这些对象组合成一个对象,并让模型使用该对象。例如,由产品组成的订单。不要先检索产品,然后再保存产品。检索订单,然后保存订单,并让您的模型处理订单。模特不应该对产品有任何了解
这称为抽象的粒度
[编辑]
评论中有一个很好的问题。当使用内存中的数据库进行测试时,我们不关心select在数据库中的工作方式。首先,控制器必须在数据库上具有功能,以统计可用于分页访问的可能记录数。IMDb(内存数据库)应该只发送一个数字。管制员永远不应该关心这个数字是多少。与实际记录相同。希望您的控制器所做的只是显示从IMDb返回的内容
[编辑]
您不应该使用活动模型和imdb对控制器进行单元测试。imdb的设置代码将有很大的摩擦。相反,当对控制器进行单元测试时,您需要对模拟、存根、伪模型进行单元测试。imdb的最佳使用是在集成测试期间或在单元测试模型时。imdb不是假的吗
我的设想是:
在我的客户机中,我使用一个表插件。服务器端处理
客户端获取请求
class MemoryProductDB {
private $products;
function MemoryProductDB() {
$this->products = array();
}
public function find($index) {
return $this->products[$index];
}
public function save($product) {
$this->products[$product['index']] = $product;
}
}
public function testSkuTable() {
$skus = array(
array('id' => '1', 'data' => 'data1'),
array('id' => '2', 'data' => 'data2'),
array('id' => '3', 'data' => 'data3'));
$names = array(
'id',
'data');
$start_row = $this->parameters['start_row'];
$num_rows = $this->parameters['num_rows'];
$sort_col = $this->parameters['sort_col'];
$search = $this->parameters['search'];
$requestSequence = $this->parameters['request_sequence'];
$direction = $this->parameters['dir'];
$filterTotals = 1;
$totalRecords = 1;
$this->gateway->expects($this->once())
->method('names')
->with($this->vendor)
->will($this->returnValue($names));
$this->gateway->expects($this->once())
->method('skus')
->with($this->vendor, $names, $start_row, $num_rows, $sort_col, $search, $direction)
->will($this->returnValue($skus));
$this->gateway->expects($this->once())
->method('filterTotals')
->will($this->returnValue($filterTotals));
$this->gateway->expects($this->once())
->method('totalRecords')
->with($this->vendor)
->will($this->returnValue($totalRecords));
$expectJson = '{"sEcho": '.$requestSequence.', "iTotalRecords": '.$totalRecords.', "iTotalDisplayRecords": '.$filterTotals.', "aaData": [ ["1","data1"],["2","data2"],["3","data3"]] }';
$actualJson = $this->skusModel->skuTable($this->vendor, $this->parameters);
$this->assertEquals($expectJson, $actualJson);
}
public function skuTable($vendor, $parameterList) {
$startRow = $parameterList['start_row'];
$numRows = $parameterList['num_rows'];
$sortCols = $parameterList['sort_col'];
$search = $parameterList['search'];
if($search == null) {
$search = "";
}
$requestSequence = $parameterList['request_sequence'];
$direction = $parameterList['dir'];
$names = $this->propertyNames($vendor);
$skus = $this->skusList($vendor, $names, $startRow, $numRows, $sortCols, $search, $direction);
$filterTotals = $this->filterTotals($vendor, $names, $startRow, $numRows, $sortCols, $search, $direction);
$totalRecords = $this->totalRecords($vendor);
return $this->buildJson($requestSequence, $totalRecords, $filterTotals, $skus, $names);
}
public function skusList($vendor, $names, $start_row, $num_rows, $sort_col, $search, $direction) {
return $this->skusGateway->skus($vendor, $names, $start_row, $num_rows, $sort_col, $search, $direction);
}