如何在DELETE SQL语句期间强制数据层抛出异常



我有一个从表中删除行的方法。我正在为它编写单元测试。其中一个测试用例必须在删除时引发错误条件,才能测试try/catch块的catch。我一辈子都想不出如何让一个错误被抓住。ADO,EF。。。什么都可以。

感谢

我有一个从表中删除行的方法。我正在写单元

除非该方法实际上包含可测试的内容,否则您可能只需要花费时间来练习框架功能。作为集成测试的一部分,这并没有错,但它可能不是一个很好的单元测试。

让我们假设在单元测试的方法中有的东西。隔离该功能的一种干净方法是将依赖关系的mock注入到正在测试的类中。

在这种情况下,听起来依赖关系应该是ADO。Net和/或EF。其中一个mock可以配置为抛出异常。

public class MyClass
{
private readonly IRepository _repository;
public MyClass( IRepository repository )
{
_repository = repository;
}
public void DoSomethingThatMightThrow()
{
// some logic that you want to test
// this might throw
var obj = _repository.Delete( 123 );
// some logic that you want to test
}
}
[TestMethod]
public void ATest()
{
// uses Moq framework, but any mocking framework should do this
var repository = new Mock<IRepository>();
repository.Setup( o => o.Delete( It.IsAny<int>() ) ).Throws( new DataException() );
var obj = new MyClass( repository );
obj.DoSomethingThatMightThrow();
}

我目前正在阅读《单元测试的艺术》,该书讨论了如何识别好的单元。作者断言,测试不必映射到单个方法,但测试应该隔离逻辑单元并易于重复。在单元测试中依赖数据库很少是一个好主意(同样,数据访问可能是一个伟大的集成测试的一部分)。

首先:试着像TimMedora所展示的那样嘲笑它。

但是,如果你做不到,你可以用很多方法来解决它,但这需要一些时间、代码,而且并不总是可能的,这取决于你的数据库引擎、数据库结构、数据库内容等。

尝试使用任何与查询无关的方法!DB引擎通常有大量的额外功能,这些功能可能会在查询过程中导致错误!

例如:

  • 在数据库上创建新的用户帐户
  • 为该帐户添加除该表上的DELETE之外的所有典型权限
  • 将该特定测试的设置更改为以该用户身份登录

结果:由于未授予所需的权限,删除任何行的尝试都将中止。

另一个例子:

  • 创建一个伪表RowLock(id int)
  • 在该列上添加约束,使其成为以TestedTable的PrimaryKey为目标的foreign key
  • 向RowLock表中添加一行,ID等于TestedTable中的某一行

结果:现在您将能够删除TestedTable中的任何行,除了RowLock标记的行,并且由于FK约束,尝试删除标记的行将中止。

您甚至可以更改测试的设置以执行额外的更改(添加用户、添加RowLock表等),然后在测试结束后的拆卸过程中对其进行清理(删除用户、删除RowLock表等等)。。但正如我所说,这一切都需要大量的工作。

我不推荐这样的方法,因为它们非常有限(行锁定仅为删除/更新,权限仅为每个数据库、每个表或每个列,等等)。但它们仍然是一个很好的最后选择,因为它们具有几乎总是可能的优势——就像RowLock一样,它只需要DB支持检查的FK约束。

相关内容

最新更新